scrobbler 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +1 -0
- data/MIT-LICENSE +19 -0
- data/{Manifest.txt → Manifest} +16 -9
- data/README.txt +37 -1
- data/Rakefile +13 -61
- data/examples/scrobble.rb +32 -0
- data/lib/scrobbler.rb +6 -1
- data/lib/scrobbler/playing.rb +49 -0
- data/lib/scrobbler/rest.rb +1 -1
- data/lib/scrobbler/scrobble.rb +66 -0
- data/lib/scrobbler/simpleauth.rb +59 -0
- data/scrobbler.gemspec +41 -0
- data/website/css/common.css +47 -0
- data/website/index.html +113 -0
- metadata +108 -62
- data/lib/scrobbler/version.rb +0 -9
data/History.txt
CHANGED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2007 John Nunemaker
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/{Manifest.txt → Manifest}
RENAMED
@@ -1,24 +1,28 @@
|
|
1
|
-
History.txt
|
2
|
-
Manifest.txt
|
3
|
-
README.txt
|
4
|
-
Rakefile
|
5
|
-
setup.rb
|
6
1
|
examples/album.rb
|
7
2
|
examples/artist.rb
|
3
|
+
examples/scrobble.rb
|
8
4
|
examples/tag.rb
|
9
5
|
examples/track.rb
|
10
6
|
examples/user.rb
|
11
|
-
|
7
|
+
History.txt
|
12
8
|
lib/scrobbler/album.rb
|
13
9
|
lib/scrobbler/artist.rb
|
14
10
|
lib/scrobbler/base.rb
|
15
11
|
lib/scrobbler/chart.rb
|
12
|
+
lib/scrobbler/playing.rb
|
16
13
|
lib/scrobbler/rest.rb
|
14
|
+
lib/scrobbler/scrobble.rb
|
15
|
+
lib/scrobbler/simpleauth.rb
|
17
16
|
lib/scrobbler/tag.rb
|
18
17
|
lib/scrobbler/track.rb
|
19
18
|
lib/scrobbler/user.rb
|
20
|
-
lib/scrobbler
|
21
|
-
|
19
|
+
lib/scrobbler.rb
|
20
|
+
Manifest
|
21
|
+
MIT-LICENSE
|
22
|
+
Rakefile
|
23
|
+
README.txt
|
24
|
+
scrobbler.gemspec
|
25
|
+
setup.rb
|
22
26
|
test/fixtures/xml/album/info.xml
|
23
27
|
test/fixtures/xml/artist/fans.xml
|
24
28
|
test/fixtures/xml/artist/similar.xml
|
@@ -50,9 +54,12 @@ test/fixtures/xml/user/weeklychartlist.xml
|
|
50
54
|
test/fixtures/xml/user/weeklytrackchart.xml
|
51
55
|
test/fixtures/xml/user/weeklytrackchart_from_1138536002_to_1139140802.xml
|
52
56
|
test/mocks/rest.rb
|
57
|
+
test/test_helper.rb
|
53
58
|
test/unit/album_test.rb
|
54
59
|
test/unit/artist_test.rb
|
55
60
|
test/unit/chart_test.rb
|
56
61
|
test/unit/tag_test.rb
|
57
62
|
test/unit/track_test.rb
|
58
|
-
test/unit/user_test.rb
|
63
|
+
test/unit/user_test.rb
|
64
|
+
website/css/common.css
|
65
|
+
website/index.html
|
data/README.txt
CHANGED
@@ -68,4 +68,40 @@ Below is just a sampling of how easy this lib is to use.
|
|
68
68
|
track = Scrobbler::Track.new('Carrie Underwood', 'Before He Cheats')
|
69
69
|
puts 'Fans'
|
70
70
|
puts "=" * 4
|
71
|
-
track.fans.each { |u| puts "(#{u.weight}) #{u.username}" }
|
71
|
+
track.fans.each { |u| puts "(#{u.weight}) #{u.username}" }
|
72
|
+
|
73
|
+
== Simple Authentication (for Scrobbling)
|
74
|
+
|
75
|
+
auth = Scrobbler::SimpleAuth.new(:user => 'chunky', :password => 'bacon')
|
76
|
+
auth.handshake!
|
77
|
+
|
78
|
+
puts "Auth Status: #{auth.status}"
|
79
|
+
puts "Session ID: #{auth.session_id}"
|
80
|
+
puts "Now Playing URL: #{auth.now_playing_url}"
|
81
|
+
puts "Submission URL: #{auth.submission_url}"
|
82
|
+
|
83
|
+
== Scrobbling
|
84
|
+
|
85
|
+
scrobble = Scrobbler::Scrobble.new(:session_id => auth.session_id,
|
86
|
+
:submission_url => auth.submission_url,
|
87
|
+
:artist => 'Coldplay',
|
88
|
+
:track => 'Viva La Vida',
|
89
|
+
:album => "Viva La Vida",
|
90
|
+
:time => Time.new,
|
91
|
+
:length => 244,
|
92
|
+
:track_number => 7)
|
93
|
+
scrobble.submit!
|
94
|
+
puts "Scrobbler Submission Status: #{scrobble.status}"
|
95
|
+
|
96
|
+
== Now Playing Submission
|
97
|
+
|
98
|
+
playing = Scrobbler::Playing.new(:session_id => auth.session_id,
|
99
|
+
:now_playing_url => auth.now_playing_url,
|
100
|
+
:artist => 'Anberlin',
|
101
|
+
:track => 'Readyfuels',
|
102
|
+
:album => 'Blueprints For the Black Market',
|
103
|
+
:length => 218,
|
104
|
+
:track_number => 1)
|
105
|
+
|
106
|
+
playing.submit!
|
107
|
+
puts "Playing Submission Status: #{playing.status}"
|
data/Rakefile
CHANGED
@@ -1,56 +1,15 @@
|
|
1
|
+
# Rakefile
|
1
2
|
require 'rubygems'
|
2
3
|
require 'rake'
|
3
|
-
require '
|
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')
|
4
|
+
require 'echoe'
|
13
5
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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.
|
6
|
+
Echoe.new('scrobbler', '0.2.0') do |p|
|
7
|
+
p.description = "wrapper for audioscrobbler (last.fm) web services"
|
8
|
+
p.url = "http://scrobbler.rubyforge.org"
|
9
|
+
p.author = "John Nunemaker"
|
10
|
+
p.email = "nunemaker@gmail.com"
|
11
|
+
p.extra_deps = [['hpricot', '>=0.4.86'], ['activesupport', '>=1.4.2']]
|
12
|
+
p.need_tar_gz = false
|
54
13
|
end
|
55
14
|
|
56
15
|
desc 'Upload website files to rubyforge'
|
@@ -63,16 +22,9 @@ task :website do
|
|
63
22
|
sh %{rsync -av #{local_dir}/ #{host}:#{remote_dir}}
|
64
23
|
end
|
65
24
|
|
66
|
-
desc '
|
67
|
-
task :
|
68
|
-
|
69
|
-
task
|
70
|
-
unless ENV['VERSION']
|
71
|
-
puts 'Must pass a VERSION=x.y.z release version'
|
72
|
-
exit
|
73
|
-
end
|
74
|
-
unless ENV['VERSION'] == VERS
|
75
|
-
puts "Please update your version.rb to match the release version, currently #{VERS}"
|
76
|
-
exit
|
25
|
+
desc 'Preps the gem for a new release'
|
26
|
+
task :prepare do
|
27
|
+
%w[manifest build_gemspec].each do |task|
|
28
|
+
Rake::Task[task].invoke
|
77
29
|
end
|
78
30
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'scrobbler'
|
3
|
+
|
4
|
+
auth = Scrobbler::SimpleAuth.new(:user => 'chunky', :password => 'bacon')
|
5
|
+
auth.handshake!
|
6
|
+
|
7
|
+
puts "Auth Status: #{auth.status}"
|
8
|
+
puts "Session ID: #{auth.session_id}"
|
9
|
+
puts "Now Playing URL: #{auth.now_playing_url}"
|
10
|
+
puts "Submission URL: #{auth.submission_url}"
|
11
|
+
|
12
|
+
scrobble = Scrobbler::Scrobble.new(:session_id => auth.session_id,
|
13
|
+
:submission_url => auth.submission_url,
|
14
|
+
:artist => 'Coldplay',
|
15
|
+
:track => 'Viva La Vida',
|
16
|
+
:album => "Viva La Vida",
|
17
|
+
:time => Time.new,
|
18
|
+
:length => 244,
|
19
|
+
:track_number => 7)
|
20
|
+
scrobble.submit!
|
21
|
+
puts "Scrobbler Submission Status: #{scrobble.status}"
|
22
|
+
|
23
|
+
playing = Scrobbler::Playing.new(:session_id => auth.session_id,
|
24
|
+
:now_playing_url => auth.now_playing_url,
|
25
|
+
:artist => 'Anberlin',
|
26
|
+
:track => 'A Day Late',
|
27
|
+
:album => 'Never Take Friendship Personal',
|
28
|
+
:length => 214,
|
29
|
+
:track_number => 5)
|
30
|
+
|
31
|
+
playing.submit!
|
32
|
+
puts "Playing Submission Status: #{playing.status}"
|
data/lib/scrobbler.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
%w{cgi rubygems hpricot active_support}.each { |x| require x }
|
2
2
|
|
3
|
+
$: << File.expand_path(File.dirname(__FILE__))
|
4
|
+
|
3
5
|
require 'scrobbler/base'
|
4
6
|
|
5
7
|
require 'scrobbler/album'
|
@@ -9,5 +11,8 @@ require 'scrobbler/user'
|
|
9
11
|
require 'scrobbler/tag'
|
10
12
|
require 'scrobbler/track'
|
11
13
|
|
14
|
+
require 'scrobbler/simpleauth'
|
15
|
+
require 'scrobbler/scrobble'
|
16
|
+
require 'scrobbler/playing'
|
17
|
+
|
12
18
|
require 'scrobbler/rest'
|
13
|
-
require 'scrobbler/version'
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Scrobbler
|
2
|
+
class Playing
|
3
|
+
# you should read last.fm/api/submissions#np first!
|
4
|
+
|
5
|
+
attr_accessor :session_id, :now_playing_url, :artist, :track,
|
6
|
+
:album, :length, :track_number, :mb_track_id
|
7
|
+
attr_reader :status
|
8
|
+
|
9
|
+
def initialize(args = {})
|
10
|
+
@session_id = args[:session_id] # from Scrobbler::SimpleAuth
|
11
|
+
@now_playing_url = args[:now_playing_url] # from Scrobbler::SimpleAuth (can change)
|
12
|
+
@artist = args[:artist] # track artist
|
13
|
+
@track = args[:track] # track name
|
14
|
+
@album = args[:album] || '' # track album (optional)
|
15
|
+
@length = args[:length] || '' # track length in seconds (optional)
|
16
|
+
@track_number = args[:track_number] || '' # track number (optional)
|
17
|
+
@mb_track_id = args[:mb_track_id] || '' # MusicBrainz track ID (optional)
|
18
|
+
|
19
|
+
if [@session_id, @now_playing_url, @artist, @track].any?(&:empty?)
|
20
|
+
raise ArgumentError, 'Missing required argument'
|
21
|
+
elsif !@length.to_s.empty? && @length.to_i <= 30 # see last.fm/api
|
22
|
+
raise ArgumentError, 'Length must be greater than 30 seconds'
|
23
|
+
end
|
24
|
+
|
25
|
+
@connection = REST::Connection.new(@now_playing_url)
|
26
|
+
end
|
27
|
+
|
28
|
+
def submit!
|
29
|
+
query = { :s => @session_id,
|
30
|
+
:a => @artist,
|
31
|
+
:t => @track,
|
32
|
+
:b => @album,
|
33
|
+
:l => @length,
|
34
|
+
:n => @track_number,
|
35
|
+
:m => @mb_track_id }
|
36
|
+
|
37
|
+
@status = @connection.post('', query)
|
38
|
+
|
39
|
+
case @status
|
40
|
+
when /OK/
|
41
|
+
|
42
|
+
when /BADSESSION/
|
43
|
+
raise BadSessionError # rerun Scrobbler::SimpleAuth#handshake!
|
44
|
+
else
|
45
|
+
raise RequestFailedError
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/scrobbler/rest.rb
CHANGED
@@ -22,7 +22,7 @@ module Scrobbler
|
|
22
22
|
|
23
23
|
if args
|
24
24
|
# TODO: What about keys without value?
|
25
|
-
url.query = args.map { |k,v| "%s=%s" % [URI.encode(k), URI.encode(v)] }.join("&")
|
25
|
+
url.query = args.map { |k,v| "%s=%s" % [URI.encode(k.to_s), URI.encode(v.to_s)] }.join("&")
|
26
26
|
end
|
27
27
|
|
28
28
|
case method
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# exception definitions
|
2
|
+
class BadSessionError < StandardError; end
|
3
|
+
class RequestFailedError < StandardError; end
|
4
|
+
|
5
|
+
module Scrobbler
|
6
|
+
class Scrobble
|
7
|
+
# you need to read last.fm/api/submissions#subs first!
|
8
|
+
|
9
|
+
attr_accessor :session_id, :submission_url, :artist, :track, :time,
|
10
|
+
:source, :length, :album, :track_number, :mb_track_id
|
11
|
+
attr_reader :status
|
12
|
+
|
13
|
+
def initialize(args = {})
|
14
|
+
@session_id = args[:session_id] # from Scrobbler::SimpleAuth
|
15
|
+
@submission_url = args[:submission_url] # from Scrobbler::SimpleAuth (can change)
|
16
|
+
@artist = args[:artist] # track artist
|
17
|
+
@track = args[:track] # track name
|
18
|
+
@time = args[:time] # a Time object set to the time the track started playing
|
19
|
+
@source = args[:source] || 'P' # track source, see last.fm/api/submissions#subs
|
20
|
+
@length = args[:length].to_s || '' # track length in seconds
|
21
|
+
@album = args[:album] || '' # track album name (optional)
|
22
|
+
@track_number = args[:track_number] || '' # track number (optional)
|
23
|
+
@mb_track_id = args[:mb_track_id] || '' # MusicBrainz track ID (optional)
|
24
|
+
|
25
|
+
if [@session_id, @submission_url, @artist, @track].any?(&:empty?)
|
26
|
+
raise ArgumentError, 'Missing required argument'
|
27
|
+
elsif @time.class.to_s != 'Time'
|
28
|
+
raise ArgumentError, ":time must be a Time object"
|
29
|
+
elsif !['P','R','E','U'].include?(@source) # see last.fm/api/submissions#subs
|
30
|
+
raise ArgumentError, "Invalid source"
|
31
|
+
elsif @source == 'P' && @length.empty? # length is not optional if source is P
|
32
|
+
raise ArgumentError, 'Length must be set'
|
33
|
+
elsif !@length.empty? && @length.to_i <= 30 # see last.fm/api/submissions#subs
|
34
|
+
raise ArgumentError, 'Length must be greater than 30 seconds'
|
35
|
+
end
|
36
|
+
|
37
|
+
@connection = REST::Connection.new(@submission_url)
|
38
|
+
end
|
39
|
+
|
40
|
+
def submit!
|
41
|
+
query = { :s => @session_id,
|
42
|
+
'a[0]' => @artist,
|
43
|
+
't[0]' => @track,
|
44
|
+
'i[0]' => @time.utc.to_i,
|
45
|
+
'o[0]' => @source,
|
46
|
+
'r[0]' => @rating,
|
47
|
+
'l[0]' => @length,
|
48
|
+
'b[0]' => @album,
|
49
|
+
'n[0]' => @track_number,
|
50
|
+
'm[0]' => @mb_track_id }
|
51
|
+
|
52
|
+
@status = @connection.post('', query)
|
53
|
+
|
54
|
+
case @status
|
55
|
+
when /OK/
|
56
|
+
|
57
|
+
when /BADSESSION/
|
58
|
+
raise BadSessionError # rerun Scrobbler::SimpleAuth#handshake!
|
59
|
+
when /FAILED/
|
60
|
+
raise RequestFailedError, @status
|
61
|
+
else
|
62
|
+
raise RequestFailedError
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
|
3
|
+
# exception definitions
|
4
|
+
class BadAuthError < StandardError; end
|
5
|
+
class BannedError < StandardError; end
|
6
|
+
class BadTimeError < StandardError; end
|
7
|
+
module Scrobbler
|
8
|
+
AUTH_URL = 'http://post.audioscrobbler.com'
|
9
|
+
AUTH_VER = '1.2.1'
|
10
|
+
|
11
|
+
class SimpleAuth
|
12
|
+
# you should read last.fm/api/submissions#handshake
|
13
|
+
|
14
|
+
attr_accessor :user, :password, :client_id, :client_ver
|
15
|
+
attr_reader :status, :session_id, :now_playing_url, :submission_url
|
16
|
+
|
17
|
+
def initialize(args = {})
|
18
|
+
@user = args[:user] # last.fm username
|
19
|
+
@password = args[:password] # last.fm password
|
20
|
+
@client_id = 'rbs' # Client ID assigned by last.fm; Don't change this!
|
21
|
+
@client_ver = Scrobbler::VERSION::STRING
|
22
|
+
|
23
|
+
raise ArgumentError, 'Missing required argument' if @user.blank? || @password.blank?
|
24
|
+
|
25
|
+
@connection = REST::Connection.new(AUTH_URL)
|
26
|
+
end
|
27
|
+
|
28
|
+
def handshake!
|
29
|
+
password_hash = Digest::MD5.hexdigest(@password)
|
30
|
+
timestamp = Time.now.to_i.to_s
|
31
|
+
token = Digest::MD5.hexdigest(password_hash + timestamp)
|
32
|
+
|
33
|
+
query = { :hs => 'true',
|
34
|
+
:p => AUTH_VER,
|
35
|
+
:c => @client_id,
|
36
|
+
:v => @client_ver,
|
37
|
+
:u => @user,
|
38
|
+
:t => timestamp,
|
39
|
+
:a => token }
|
40
|
+
result = @connection.get('/', query)
|
41
|
+
|
42
|
+
@status = result.split(/\n/)[0]
|
43
|
+
case @status
|
44
|
+
when /OK/
|
45
|
+
@session_id, @now_playing_url, @submission_url = result.split(/\n/)[1,3]
|
46
|
+
when /BANNED/
|
47
|
+
raise BannedError # something is wrong with the gem, check for an update
|
48
|
+
when /BADAUTH/
|
49
|
+
raise BadAuthError # invalid user/password
|
50
|
+
when /FAILED/
|
51
|
+
raise RequestFailedError, @status
|
52
|
+
when /BADTIME/
|
53
|
+
raise BadTimeError # system time is way off
|
54
|
+
else
|
55
|
+
raise RequestFailedError
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/scrobbler.gemspec
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{scrobbler}
|
5
|
+
s.version = "0.2.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["John Nunemaker"]
|
9
|
+
s.date = %q{2008-12-03}
|
10
|
+
s.description = %q{wrapper for audioscrobbler (last.fm) web services}
|
11
|
+
s.email = %q{nunemaker@gmail.com}
|
12
|
+
s.extra_rdoc_files = ["lib/scrobbler/album.rb", "lib/scrobbler/artist.rb", "lib/scrobbler/base.rb", "lib/scrobbler/chart.rb", "lib/scrobbler/playing.rb", "lib/scrobbler/rest.rb", "lib/scrobbler/scrobble.rb", "lib/scrobbler/simpleauth.rb", "lib/scrobbler/tag.rb", "lib/scrobbler/track.rb", "lib/scrobbler/user.rb", "lib/scrobbler.rb", "README.txt"]
|
13
|
+
s.files = ["examples/album.rb", "examples/artist.rb", "examples/scrobble.rb", "examples/tag.rb", "examples/track.rb", "examples/user.rb", "History.txt", "lib/scrobbler/album.rb", "lib/scrobbler/artist.rb", "lib/scrobbler/base.rb", "lib/scrobbler/chart.rb", "lib/scrobbler/playing.rb", "lib/scrobbler/rest.rb", "lib/scrobbler/scrobble.rb", "lib/scrobbler/simpleauth.rb", "lib/scrobbler/tag.rb", "lib/scrobbler/track.rb", "lib/scrobbler/user.rb", "lib/scrobbler.rb", "Manifest", "MIT-LICENSE", "Rakefile", "README.txt", "scrobbler.gemspec", "setup.rb", "test/fixtures/xml/album/info.xml", "test/fixtures/xml/artist/fans.xml", "test/fixtures/xml/artist/similar.xml", "test/fixtures/xml/artist/topalbums.xml", "test/fixtures/xml/artist/toptags.xml", "test/fixtures/xml/artist/toptracks.xml", "test/fixtures/xml/tag/topalbums.xml", "test/fixtures/xml/tag/topartists.xml", "test/fixtures/xml/tag/toptags.xml", "test/fixtures/xml/tag/toptracks.xml", "test/fixtures/xml/track/fans.xml", "test/fixtures/xml/track/toptags.xml", "test/fixtures/xml/user/friends.xml", "test/fixtures/xml/user/neighbours.xml", "test/fixtures/xml/user/profile.xml", "test/fixtures/xml/user/recentbannedtracks.xml", "test/fixtures/xml/user/recentlovedtracks.xml", "test/fixtures/xml/user/recenttracks.xml", "test/fixtures/xml/user/systemrecs.xml", "test/fixtures/xml/user/topalbums.xml", "test/fixtures/xml/user/topartists.xml", "test/fixtures/xml/user/toptags.xml", "test/fixtures/xml/user/toptracks.xml", "test/fixtures/xml/user/weeklyalbumchart.xml", "test/fixtures/xml/user/weeklyalbumchart_from_1138536002_to_1139140802.xml", "test/fixtures/xml/user/weeklyartistchart.xml", "test/fixtures/xml/user/weeklyartistchart_from_1138536002_to_1139140802.xml", "test/fixtures/xml/user/weeklychartlist.xml", "test/fixtures/xml/user/weeklytrackchart.xml", "test/fixtures/xml/user/weeklytrackchart_from_1138536002_to_1139140802.xml", "test/mocks/rest.rb", "test/test_helper.rb", "test/unit/album_test.rb", "test/unit/artist_test.rb", "test/unit/chart_test.rb", "test/unit/tag_test.rb", "test/unit/track_test.rb", "test/unit/user_test.rb", "website/css/common.css", "website/index.html"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://scrobbler.rubyforge.org}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Scrobbler", "--main", "README.txt"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{scrobbler}
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
20
|
+
s.summary = %q{wrapper for audioscrobbler (last.fm) web services}
|
21
|
+
s.test_files = ["test/test_helper.rb", "test/unit/album_test.rb", "test/unit/artist_test.rb", "test/unit/chart_test.rb", "test/unit/tag_test.rb", "test/unit/track_test.rb", "test/unit/user_test.rb"]
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 2
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
s.add_runtime_dependency(%q<hpricot>, [">= 0.4.86"])
|
29
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 1.4.2"])
|
30
|
+
s.add_development_dependency(%q<echoe>, [">= 0"])
|
31
|
+
else
|
32
|
+
s.add_dependency(%q<hpricot>, [">= 0.4.86"])
|
33
|
+
s.add_dependency(%q<activesupport>, [">= 1.4.2"])
|
34
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
35
|
+
end
|
36
|
+
else
|
37
|
+
s.add_dependency(%q<hpricot>, [">= 0.4.86"])
|
38
|
+
s.add_dependency(%q<activesupport>, [">= 1.4.2"])
|
39
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
@media screen, projection {
|
2
|
+
/*
|
3
|
+
Copyright (c) 2007, Yahoo! Inc. All rights reserved.
|
4
|
+
Code licensed under the BSD License:
|
5
|
+
http://developer.yahoo.net/yui/license.txt
|
6
|
+
version: 2.2.0
|
7
|
+
*/
|
8
|
+
body {font:13px arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}table {font-size:inherit;font:100%;}select, input, textarea {font:99% arial,helvetica,clean,sans-serif;}pre, code {font:115% monospace;*font-size:100%;}body * {line-height:1.22em;}
|
9
|
+
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}/*ol,ul {list-style:none;}*/caption,th {text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym {border:0;}
|
10
|
+
/* end of yahoo reset and fonts */
|
11
|
+
|
12
|
+
body {color:#333; background:#4b1a1a; line-height:1.3;}
|
13
|
+
p {margin:0 0 20px;}
|
14
|
+
a {color:#4b1a1a;}
|
15
|
+
a:hover {text-decoration:none;}
|
16
|
+
strong {font-weight:bold;}
|
17
|
+
em {font-style:italics;}
|
18
|
+
h1,h2,h3,h4,h5,h6 {font-weight:bold;}
|
19
|
+
h1 {font-size:197%; margin:30px 0; color:#4b1a1a;}
|
20
|
+
h2 {font-size:174%; margin:20px 0; color:#b8111a;}
|
21
|
+
h3 {font-size:152%; margin:10px 0;}
|
22
|
+
h4 {font-size:129%; margin:10px 0;}
|
23
|
+
pre {background:#eee; padding:20px; border:1px solid #ccc; font-size:100%; overflow:auto;}
|
24
|
+
code {font-size:100%; margin:0; padding:0;}
|
25
|
+
ul, ol {margin:10px 0 10px 25px;}
|
26
|
+
ol li {margin:0 0 10px;}
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
div#wrapper {background:#fff; width:560px; margin:0 auto; padding:20px; border:10px solid #bc8c46; border-width:0 10px;}
|
33
|
+
div#header {position:relative; border-bottom:1px dotted; margin:0 0 10px; padding:0 0 10px;}
|
34
|
+
div#header p {margin:0; padding:0;}
|
35
|
+
div#header h1 {margin:0; padding:0;}
|
36
|
+
ul#nav {position:absolute; top:0; right:0; list-style:none; margin:0; padding:0;}
|
37
|
+
ul#nav li {display:inline; padding:0 0 0 5px;}
|
38
|
+
ul#nav li a {}
|
39
|
+
div#content {}
|
40
|
+
div#footer {margin:40px 0 0; border-top:1px dotted; padding:10px 0 0;}
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
}
|
data/website/index.html
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
2
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
5
|
+
<title>Scrobbler by John Nunemaker</title>
|
6
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
|
10
|
+
<div id="wrapper">
|
11
|
+
<div id="header">
|
12
|
+
<h1>Scrobbler</h1>
|
13
|
+
<p>Get your music on.</p>
|
14
|
+
|
15
|
+
<ul id="nav">
|
16
|
+
<li><a href="scrobbler/">Docs</a></li>
|
17
|
+
<li><a href="http://rubyforge.org/projects/scrobbler/">Rubyforge Page</a></li>
|
18
|
+
</ul>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<div id="content">
|
22
|
+
<p>Scrobbler is a wrapper for the <a href="http://www.audioscrobbler.net/data/webservices/">audioscrobbler (last.fm) web services</a>.</p>
|
23
|
+
|
24
|
+
<h2>Installation</h2>
|
25
|
+
|
26
|
+
<pre><code>$ sudo gem install scrobbler</code></pre>
|
27
|
+
|
28
|
+
<h2>Usage</h2>
|
29
|
+
|
30
|
+
<p>Below is just a sampling of how easy this lib is to use.</p>
|
31
|
+
|
32
|
+
<h3>Users</h3>
|
33
|
+
|
34
|
+
<pre><code class="ruby">user = Scrobbler::User.new('jnunemaker')
|
35
|
+
|
36
|
+
puts "#{user.username}'s Recent Tracks"
|
37
|
+
puts "=" * (user.username.length + 16)
|
38
|
+
user.recent_tracks.each { |t| puts t.name }
|
39
|
+
|
40
|
+
puts
|
41
|
+
puts
|
42
|
+
|
43
|
+
puts "#{user.username}'s Top Tracks"
|
44
|
+
puts "=" * (user.username.length + 13)
|
45
|
+
user.top_tracks.each { |t| puts "(#{t.playcount}) #{t.name}" }</code></pre>
|
46
|
+
|
47
|
+
<h3>Albums</h3>
|
48
|
+
|
49
|
+
<pre><code class="ruby">album = Scrobbler::Album.new('Carrie Underwood', 'Some Hearts', :include_info => true)
|
50
|
+
|
51
|
+
puts "Album: #{album.name}"
|
52
|
+
puts "Artist: #{album.artist}"
|
53
|
+
puts "Reach: #{album.reach}"
|
54
|
+
puts "URL: #{album.url}"
|
55
|
+
puts "Release Date: #{album.release_date.strftime('%m/%d/%Y')}"
|
56
|
+
|
57
|
+
puts
|
58
|
+
puts
|
59
|
+
|
60
|
+
puts "Tracks"
|
61
|
+
longest_track_name = album.tracks.collect(&:name).sort { |x, y| y.length <=> x.length }.first.length
|
62
|
+
puts "=" * longest_track_name
|
63
|
+
album.tracks.each { |t| puts t.name }</code></pre>
|
64
|
+
|
65
|
+
<h3>Artists</h3>
|
66
|
+
|
67
|
+
<pre><code class="ruby">artist = Scrobbler::Artist.new('Carrie Underwood')
|
68
|
+
|
69
|
+
puts 'Top Tracks'
|
70
|
+
puts "=" * 10
|
71
|
+
artist.top_tracks.each { |t| puts "(#{t.reach}) #{t.name}" }
|
72
|
+
|
73
|
+
puts
|
74
|
+
|
75
|
+
puts 'Similar Artists'
|
76
|
+
puts "=" * 15
|
77
|
+
artist.similar.each { |a| puts "(#{a.match}%) #{a.name}" }</code></pre>
|
78
|
+
|
79
|
+
<h3>Tags</h3>
|
80
|
+
|
81
|
+
<pre><code class="ruby">tag = Scrobbler::Tag.new('country')
|
82
|
+
|
83
|
+
puts 'Top Albums'
|
84
|
+
tag.top_albums.each { |a| puts "(#{a.count}) #{a.name} by #{a.artist}" }
|
85
|
+
|
86
|
+
puts
|
87
|
+
|
88
|
+
puts 'Top Tracks'
|
89
|
+
tag.top_tracks.each { |t| puts "(#{t.count}) #{t.name} by #{t.artist}" }</code></pre>
|
90
|
+
|
91
|
+
<h3>Tracks</h3>
|
92
|
+
|
93
|
+
<pre><code class="ruby">track = Scrobbler::Track.new('Carrie Underwood', 'Before He Cheats')
|
94
|
+
puts 'Fans'
|
95
|
+
puts "=" * 4
|
96
|
+
track.fans.each { |u| puts "(#{u.weight}) #{u.username}" }</code></pre>
|
97
|
+
</div>
|
98
|
+
|
99
|
+
<div id="footer">
|
100
|
+
<p>Created by <a href="http://addictedtonew.com/about/">John Nunemaker</a></p>
|
101
|
+
</div>
|
102
|
+
|
103
|
+
</div>
|
104
|
+
|
105
|
+
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
|
106
|
+
<script type="text/javascript">_uacct = "UA-85301-11"; urchinTracker();</script>
|
107
|
+
|
108
|
+
<!-- 103bees.com 'bee' code v1.11 - please do not make any changes! -->
|
109
|
+
<script type="text/javascript" src="http://103bees.com/bees/?bee=3672&fid=6687"></script>
|
110
|
+
<!-- 103bees.com 'bee' code -->
|
111
|
+
|
112
|
+
</body>
|
113
|
+
</html>
|
metadata
CHANGED
@@ -1,55 +1,93 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.4
|
3
|
-
specification_version: 1
|
4
2
|
name: scrobbler
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-10-23 00:00:00 -04:00
|
8
|
-
summary: wrapper for audioscrobbler (last.fm) web services
|
9
|
-
require_paths:
|
10
|
-
- lib
|
11
|
-
email: nunemaker@gmail.com
|
12
|
-
homepage: http://scrobbler.rubyforge.org
|
13
|
-
rubyforge_project: scrobbler
|
14
|
-
description: wrapper for audioscrobbler (last.fm) web services
|
15
|
-
autorequire:
|
16
|
-
default_executable:
|
17
|
-
bindir: bin
|
18
|
-
has_rdoc: true
|
19
|
-
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">"
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 0.0.0
|
24
|
-
version:
|
4
|
+
version: 0.2.0
|
25
5
|
platform: ruby
|
26
|
-
signing_key:
|
27
|
-
cert_chain:
|
28
|
-
post_install_message:
|
29
6
|
authors:
|
30
|
-
-
|
31
|
-
|
32
|
-
|
33
|
-
|
7
|
+
- John Nunemaker
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-12-03 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: hpricot
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.4.86
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: activesupport
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.4.2
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: echoe
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
description: wrapper for audioscrobbler (last.fm) web services
|
46
|
+
email: nunemaker@gmail.com
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- lib/scrobbler/album.rb
|
53
|
+
- lib/scrobbler/artist.rb
|
54
|
+
- lib/scrobbler/base.rb
|
55
|
+
- lib/scrobbler/chart.rb
|
56
|
+
- lib/scrobbler/playing.rb
|
57
|
+
- lib/scrobbler/rest.rb
|
58
|
+
- lib/scrobbler/scrobble.rb
|
59
|
+
- lib/scrobbler/simpleauth.rb
|
60
|
+
- lib/scrobbler/tag.rb
|
61
|
+
- lib/scrobbler/track.rb
|
62
|
+
- lib/scrobbler/user.rb
|
63
|
+
- lib/scrobbler.rb
|
34
64
|
- README.txt
|
35
|
-
|
36
|
-
- setup.rb
|
65
|
+
files:
|
37
66
|
- examples/album.rb
|
38
67
|
- examples/artist.rb
|
68
|
+
- examples/scrobble.rb
|
39
69
|
- examples/tag.rb
|
40
70
|
- examples/track.rb
|
41
71
|
- examples/user.rb
|
42
|
-
-
|
72
|
+
- History.txt
|
43
73
|
- lib/scrobbler/album.rb
|
44
74
|
- lib/scrobbler/artist.rb
|
45
75
|
- lib/scrobbler/base.rb
|
46
76
|
- lib/scrobbler/chart.rb
|
77
|
+
- lib/scrobbler/playing.rb
|
47
78
|
- lib/scrobbler/rest.rb
|
79
|
+
- lib/scrobbler/scrobble.rb
|
80
|
+
- lib/scrobbler/simpleauth.rb
|
48
81
|
- lib/scrobbler/tag.rb
|
49
82
|
- lib/scrobbler/track.rb
|
50
83
|
- lib/scrobbler/user.rb
|
51
|
-
- lib/scrobbler
|
52
|
-
-
|
84
|
+
- lib/scrobbler.rb
|
85
|
+
- Manifest
|
86
|
+
- MIT-LICENSE
|
87
|
+
- Rakefile
|
88
|
+
- README.txt
|
89
|
+
- scrobbler.gemspec
|
90
|
+
- setup.rb
|
53
91
|
- test/fixtures/xml/album/info.xml
|
54
92
|
- test/fixtures/xml/artist/fans.xml
|
55
93
|
- test/fixtures/xml/artist/similar.xml
|
@@ -81,43 +119,51 @@ files:
|
|
81
119
|
- test/fixtures/xml/user/weeklytrackchart.xml
|
82
120
|
- test/fixtures/xml/user/weeklytrackchart_from_1138536002_to_1139140802.xml
|
83
121
|
- test/mocks/rest.rb
|
122
|
+
- test/test_helper.rb
|
84
123
|
- test/unit/album_test.rb
|
85
124
|
- test/unit/artist_test.rb
|
86
125
|
- test/unit/chart_test.rb
|
87
126
|
- test/unit/tag_test.rb
|
88
127
|
- test/unit/track_test.rb
|
89
128
|
- test/unit/user_test.rb
|
90
|
-
|
91
|
-
-
|
129
|
+
- website/css/common.css
|
130
|
+
- website/index.html
|
131
|
+
has_rdoc: true
|
132
|
+
homepage: http://scrobbler.rubyforge.org
|
133
|
+
post_install_message:
|
92
134
|
rdoc_options:
|
135
|
+
- --line-numbers
|
136
|
+
- --inline-source
|
137
|
+
- --title
|
138
|
+
- Scrobbler
|
93
139
|
- --main
|
94
140
|
- README.txt
|
95
|
-
|
96
|
-
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
141
|
+
require_paths:
|
142
|
+
- lib
|
143
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: "0"
|
148
|
+
version:
|
149
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: "1.2"
|
154
|
+
version:
|
103
155
|
requirements: []
|
104
156
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
-
|
116
|
-
|
117
|
-
|
118
|
-
version_requirements: !ruby/object:Gem::Version::Requirement
|
119
|
-
requirements:
|
120
|
-
- - ">="
|
121
|
-
- !ruby/object:Gem::Version
|
122
|
-
version: 1.4.2
|
123
|
-
version:
|
157
|
+
rubyforge_project: scrobbler
|
158
|
+
rubygems_version: 1.3.1
|
159
|
+
signing_key:
|
160
|
+
specification_version: 2
|
161
|
+
summary: wrapper for audioscrobbler (last.fm) web services
|
162
|
+
test_files:
|
163
|
+
- test/test_helper.rb
|
164
|
+
- test/unit/album_test.rb
|
165
|
+
- test/unit/artist_test.rb
|
166
|
+
- test/unit/chart_test.rb
|
167
|
+
- test/unit/tag_test.rb
|
168
|
+
- test/unit/track_test.rb
|
169
|
+
- test/unit/user_test.rb
|