scrobbler-ng 2.0.2 → 2.0.3
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/.gitignore +1 -0
- data/VERSION.yml +1 -1
- data/lib/scrobbler.rb +1 -4
- data/lib/scrobbler/album.rb +19 -5
- data/lib/scrobbler/authentication.rb +63 -0
- data/lib/scrobbler/event.rb +3 -2
- data/lib/scrobbler/session.rb +35 -2
- data/lib/scrobbler/track.rb +7 -1
- data/test/mocks/rest.rb +12 -0
- data/test/unit/album_spec.rb +11 -1
- data/test/unit/artist_spec.rb +1 -1
- data/test/unit/authentication_spec.rb +51 -0
- data/test/unit/event_spec.rb +1 -5
- data/test/unit/tag_spec.rb +1 -1
- data/test/unit/track_spec.rb +10 -0
- data/test/unit/user_spec.rb +2 -2
- metadata +29 -34
- data/lib/scrobbler/auth.rb +0 -59
- data/lib/scrobbler/playing.rb +0 -49
- data/lib/scrobbler/simpleauth.rb +0 -60
- data/tasks/metric_fu.rake +0 -27
- data/tasks/reek.rake +0 -13
- data/tasks/roodi.rake +0 -13
- data/test/unit/auth_spec.rb +0 -36
data/.gitignore
CHANGED
data/VERSION.yml
CHANGED
data/lib/scrobbler.rb
CHANGED
@@ -24,12 +24,9 @@ require 'scrobbler/session'
|
|
24
24
|
require 'scrobbler/tag'
|
25
25
|
require 'scrobbler/track'
|
26
26
|
|
27
|
-
require 'scrobbler/auth'
|
28
27
|
require 'scrobbler/library'
|
29
28
|
require 'scrobbler/playlist'
|
30
29
|
require 'scrobbler/radio'
|
31
30
|
|
32
|
-
require 'scrobbler/simpleauth'
|
33
|
-
require 'scrobbler/playing'
|
34
|
-
|
35
31
|
require 'scrobbler/rest'
|
32
|
+
require 'scrobbler/authentication'
|
data/lib/scrobbler/album.rb
CHANGED
@@ -3,7 +3,8 @@
|
|
3
3
|
require File.expand_path('basexmlinfo.rb', File.dirname(__FILE__))
|
4
4
|
|
5
5
|
module Scrobbler
|
6
|
-
#
|
6
|
+
# Class for handling album.* requests to the Last.fm API and reading Album data
|
7
|
+
# provided in return.
|
7
8
|
class Album < BaseXmlInfo
|
8
9
|
include Scrobbler::ImageObjectFuncs
|
9
10
|
|
@@ -116,10 +117,13 @@ module Scrobbler
|
|
116
117
|
end
|
117
118
|
end
|
118
119
|
|
119
|
-
# Tag an album using a list of user supplied tags.
|
120
|
-
|
121
|
-
|
122
|
-
|
120
|
+
# Tag an album using a list of user supplied tags.
|
121
|
+
#
|
122
|
+
# @param [Scrobbler::Session] session A valid session to authenticate access
|
123
|
+
# @param [Array<String>] tags Tags to add to this album
|
124
|
+
# @return [nil]
|
125
|
+
def add_tags(session, tags)
|
126
|
+
Base.post_request('album.addTags', {:sk => session.key, :signed => true, :tags => tags.join(',')})
|
123
127
|
end
|
124
128
|
|
125
129
|
# Get the tags applied by an individual user to an album on Last.fm.
|
@@ -133,5 +137,15 @@ module Scrobbler
|
|
133
137
|
# This function require authentication, but SimpleAuth is not yet 2.0
|
134
138
|
raise NotImplementedError
|
135
139
|
end
|
140
|
+
|
141
|
+
# Get the links to buy this album
|
142
|
+
def buylinks()
|
143
|
+
raise NotImplementedError
|
144
|
+
end
|
145
|
+
|
146
|
+
# Share this album with a friend
|
147
|
+
def share()
|
148
|
+
raise NotImplementedError
|
149
|
+
end
|
136
150
|
end
|
137
151
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'digest/md5'
|
3
|
+
|
4
|
+
module Scrobbler
|
5
|
+
class Authentication < Base
|
6
|
+
|
7
|
+
def initialize(data = {})
|
8
|
+
populate_data(data)
|
9
|
+
super()
|
10
|
+
|
11
|
+
@digest = Digest::MD5.new
|
12
|
+
|
13
|
+
# Check if the input parameters are valid
|
14
|
+
if @username.nil? || @username.empty?
|
15
|
+
raise ArgumentError, 'Username is required'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def auth_token(password)
|
20
|
+
@digest.hexdigest(@username + @digest.hexdigest(password))
|
21
|
+
end
|
22
|
+
|
23
|
+
def mobile_session(password)
|
24
|
+
xml = Base.request('auth.getMobileSession', {:username => @username, :signed => true, :authToken => auth_token(password)})
|
25
|
+
load_session_out_of_session_request(xml)
|
26
|
+
end
|
27
|
+
|
28
|
+
def session(tokenStr)
|
29
|
+
xml = Base.request('auth.getSession', {:signed => true, :token => tokenStr})
|
30
|
+
load_session_out_of_session_request(xml)
|
31
|
+
end
|
32
|
+
|
33
|
+
def load_session_out_of_session_request(xml)
|
34
|
+
# Find the session node
|
35
|
+
xml.root.children.each do |child|
|
36
|
+
next unless child.name == 'session'
|
37
|
+
return Session.new(:xml => child)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def token
|
42
|
+
xml = Base.request('auth.getToken', {:signed => true})
|
43
|
+
# Grep the token
|
44
|
+
xml.root.children.each do |child|
|
45
|
+
next unless child.name == 'token'
|
46
|
+
return child.content
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def webservice_session_url(callback=nil)
|
51
|
+
if not callback.nil? then
|
52
|
+
cb = "&cb=" + CGI::escape(callback)
|
53
|
+
else
|
54
|
+
cb = ''
|
55
|
+
end
|
56
|
+
'http://www.last.fm/api/auth/?api_key=' + @@api_key + cb
|
57
|
+
end
|
58
|
+
|
59
|
+
def desktop_session_url(tokenStr)
|
60
|
+
webservice_session_url + '&token=' + tokenStr
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/scrobbler/event.rb
CHANGED
@@ -123,8 +123,9 @@ module Scrobbler
|
|
123
123
|
raise NotImplementedError
|
124
124
|
end
|
125
125
|
|
126
|
-
def attend
|
127
|
-
|
126
|
+
def attend
|
127
|
+
# This function require authentication, but SimpleAuth is not yet 2.0
|
128
|
+
raise NotImplementedError
|
128
129
|
end
|
129
130
|
|
130
131
|
def share
|
data/lib/scrobbler/session.rb
CHANGED
@@ -1,9 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path('basexml.rb', File.dirname(__FILE__))
|
4
|
+
|
1
5
|
module Scrobbler
|
2
|
-
class Session <
|
6
|
+
class Session < BaseXml
|
3
7
|
attr_reader :key, :name, :subscriber
|
4
8
|
|
5
9
|
def initialize(data={})
|
6
|
-
|
10
|
+
raise ArgumentError unless data.kind_of?(Hash)
|
11
|
+
super(data)
|
7
12
|
end
|
13
|
+
|
14
|
+
# Load the data for this object out of a XML-Node
|
15
|
+
#
|
16
|
+
# @param [LibXML::XML::Node] node The XML node containing the information
|
17
|
+
# @return [nil]
|
18
|
+
def load_from_xml(node)
|
19
|
+
# Get all information from the root's children nodes
|
20
|
+
node.children.each do |child|
|
21
|
+
case child.name
|
22
|
+
when 'name'
|
23
|
+
@name = child.content
|
24
|
+
when 'key'
|
25
|
+
@key = child.content
|
26
|
+
when 'subscriber'
|
27
|
+
if child.content == '1' then
|
28
|
+
@subscriber = true
|
29
|
+
else
|
30
|
+
@subscriber = false
|
31
|
+
end
|
32
|
+
when 'text'
|
33
|
+
# ignore, these are only blanks
|
34
|
+
when '#text'
|
35
|
+
# libxml-jruby version of blanks
|
36
|
+
else
|
37
|
+
raise NotImplementedError, "Field '#{child.name}' not known (#{child.content})"
|
38
|
+
end #^ case
|
39
|
+
end #^ do |child|
|
40
|
+
end #^ load_from_xml
|
8
41
|
end
|
9
42
|
end
|
data/lib/scrobbler/track.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require File.expand_path('basexmlinfo.rb', File.dirname(__FILE__))
|
4
|
+
|
3
5
|
module Scrobbler
|
4
6
|
class Track < Base
|
5
7
|
# Load Helper modules
|
@@ -10,6 +12,10 @@ module Scrobbler
|
|
10
12
|
attr_reader :streamable, :album, :date, :now_playing, :tagcount
|
11
13
|
attr_reader :duration, :listeners
|
12
14
|
|
15
|
+
def self.fingerprint_metadata(fpid)
|
16
|
+
Base.get('track.getFingerprintMetadata', :tracks, Track, {:fingerprintid => fpid})
|
17
|
+
end
|
18
|
+
|
13
19
|
def self.new_from_libxml(xml)
|
14
20
|
data = {}
|
15
21
|
xml.children.each do |child|
|
@@ -32,7 +38,7 @@ module Scrobbler
|
|
32
38
|
end
|
33
39
|
|
34
40
|
|
35
|
-
data[:rank] = xml['rank'].
|
41
|
+
data[:rank] = xml['rank'].to_f if xml['rank']
|
36
42
|
data[:now_playing] = true if xml['nowplaying'] && xml['nowplaying'] == 'true'
|
37
43
|
|
38
44
|
data[:now_playing] = false if data[:now_playing].nil?
|
data/test/mocks/rest.rb
CHANGED
@@ -71,6 +71,8 @@ register_fw('artist=Cher&track=Before%20He%20Cheats&api_key=foo123&method=track.
|
|
71
71
|
'track', 'fans.xml')
|
72
72
|
register_fw('artist=Cher&track=Before%20He%20Cheats&api_key=foo123&method=track.gettoptags',
|
73
73
|
'track', 'toptags.xml')
|
74
|
+
register_fw('fingerprintid=1234&api_key=foo123&method=track.getFingerprintMetadata',
|
75
|
+
'track', 'fingerprintmetadata.xml')
|
74
76
|
|
75
77
|
## Geo
|
76
78
|
FakeWeb.register_uri(:get, WEB_BASE + 'location=Manchester&api_key=foo123&method=geo.getevents', :body => File.join([FIXTURES_BASE, 'geo', 'events-p1.xml']))
|
@@ -112,3 +114,13 @@ register_fw('user=jnunemaker&api_key=foo123&method=user.getlovedtracks',
|
|
112
114
|
# Album
|
113
115
|
register_fw('artist=Carrie%20Underwood&album=Some%20Hearts&api_key=foo123&method=album.getinfo',
|
114
116
|
'album', 'info.xml')
|
117
|
+
FakeWeb.register_uri(:post, WEB_BASE + 'api_key=foo123&method=album.addTags&sk=d580d57f32848f5dcf574d1ce18d78b2&tags=tag1%2Ctag2&api_sig=ab00d1e2baf1c820f889f604ca86535d',
|
118
|
+
:body => File.join([FIXTURES_BASE, 'album', 'addtags.xml']))
|
119
|
+
|
120
|
+
# Authentication
|
121
|
+
register_fw('api_key=foo123&authToken=3cf8871e1ce17fbfad72d49007ec2aad&method=auth.getMobileSession&username=john&api_sig=6b9c4b9732a6bb0339bcbbc9ecbcd4dd',
|
122
|
+
'auth', 'mobile.xml')
|
123
|
+
register_fw('api_key=foo123&method=auth.getToken&api_sig=1cc6b6f01a027f166a21ca8fe0c693b3',
|
124
|
+
'auth', 'token.xml')
|
125
|
+
register_fw('api_key=foo123&method=auth.getSession&token=0e6af5cd2fff6b314994af5b0c58ecc1&api_sig=2f8e52b15b36e8ca1356e7337364b84b',
|
126
|
+
'auth', 'session.xml')
|
data/test/unit/album_spec.rb
CHANGED
@@ -4,6 +4,7 @@ describe Scrobbler::Album do
|
|
4
4
|
|
5
5
|
before(:each) do
|
6
6
|
@album = Scrobbler::Album.new(:name => 'Some Hearts', :artist => 'Carrie Underwood')
|
7
|
+
@session = Scrobbler::Session.new(:name => 'john', :subscriber => false, :key => 'd580d57f32848f5dcf574d1ce18d78b2')
|
7
8
|
end
|
8
9
|
|
9
10
|
it 'should know the artist' do
|
@@ -16,13 +17,18 @@ describe Scrobbler::Album do
|
|
16
17
|
|
17
18
|
it "should implement all methods from the Last.fm 2.0 API" do
|
18
19
|
@album.should respond_to(:add_tags)
|
20
|
+
@album.should respond_to(:buylinks)
|
19
21
|
@album.should respond_to(:load_info)
|
20
22
|
@album.should respond_to(:tags)
|
23
|
+
@album.should respond_to(:top_tags)
|
21
24
|
@album.should respond_to(:remove_tag)
|
22
25
|
@album.should respond_to(:search)
|
26
|
+
@album.should respond_to(:share)
|
23
27
|
end
|
24
28
|
|
25
|
-
it 'should be able to add tags'
|
29
|
+
it 'should be able to add tags' do
|
30
|
+
@album.add_tags(@session, ['tag1', 'tag2'])
|
31
|
+
end
|
26
32
|
|
27
33
|
it 'should be able to load album info' do
|
28
34
|
@album.load_info
|
@@ -48,4 +54,8 @@ describe Scrobbler::Album do
|
|
48
54
|
it 'should be able to remove tags'
|
49
55
|
|
50
56
|
it 'should be able to search for albums'
|
57
|
+
|
58
|
+
it 'should be able to get the links to buy this album'
|
59
|
+
|
60
|
+
it 'should be able to share a album with a friend'
|
51
61
|
end
|
data/test/unit/artist_spec.rb
CHANGED
@@ -109,7 +109,7 @@ describe Scrobbler::Artist do
|
|
109
109
|
@artist.top_tracks.should be_kind_of(Array)
|
110
110
|
@artist.top_tracks.should have(4).items
|
111
111
|
@artist.top_tracks.first.should be_kind_of(Scrobbler::Track)
|
112
|
-
@artist.top_tracks.first.rank.should eql(1)
|
112
|
+
@artist.top_tracks.first.rank.should eql(1.0)
|
113
113
|
@artist.top_tracks.first.name.should eql('Nothing Else Matters')
|
114
114
|
@artist.top_tracks.first.playcount.should eql(537704)
|
115
115
|
@artist.top_tracks.first.mbid.should eql('')
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
describe Scrobbler::Authentication do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@auth = Scrobbler::Authentication.new(:username => 'john')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should implement' do
|
10
|
+
@auth.should respond_to(:session)
|
11
|
+
@auth.should respond_to(:mobile_session)
|
12
|
+
@auth.should respond_to(:token)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should be able to authorize a mobile session' do
|
16
|
+
@session = @auth.mobile_session('doe')
|
17
|
+
@session.key.should eql('d580d57f32848f5dcf574d1ce18d78b2')
|
18
|
+
@session.subscriber.should be_false
|
19
|
+
@session.name.should eql('john')
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should be able to authorize a web session' do
|
23
|
+
# Check URL generation
|
24
|
+
session_url = @auth.webservice_session_url
|
25
|
+
session_url.should match /http\:\/\/www.last.fm\/api\/auth\/\?api_key=[^&?]*/
|
26
|
+
session_url_cb = @auth.webservice_session_url("http://www.example.com/callback")
|
27
|
+
session_url_cb.should match /http\:\/\/www.last.fm\/api\/auth\/\?api_key=[^&?]*&cb=[^&?]*/
|
28
|
+
# Handle callback -- mocking this --
|
29
|
+
token = @auth.token
|
30
|
+
# Check session generation
|
31
|
+
@session = @auth.session(token)
|
32
|
+
@session.key.should eql('d580d57f32848f5dcf574d1ce18d78b2')
|
33
|
+
@session.subscriber.should be_false
|
34
|
+
@session.name.should eql('john')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should be able to authroize a desktop session' do
|
38
|
+
# Check URL generation
|
39
|
+
token = @auth.token
|
40
|
+
session_url = @auth.desktop_session_url(token)
|
41
|
+
session_url.should match /http\:\/\/www.last.fm\/api\/auth\/\?api_key=[^&?]*&token=[^&?]*/
|
42
|
+
# -- Intemediate step needed in production to let the user grant this application access
|
43
|
+
# Check session generation
|
44
|
+
@session = @auth.session(token)
|
45
|
+
@session.key.should eql('d580d57f32848f5dcf574d1ce18d78b2')
|
46
|
+
@session.subscriber.should be_false
|
47
|
+
@session.name.should eql('john')
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
data/test/unit/event_spec.rb
CHANGED
@@ -3,8 +3,6 @@ require File.dirname(__FILE__) + '/../spec_helper.rb'
|
|
3
3
|
describe Scrobbler::Event do
|
4
4
|
|
5
5
|
before(:all) do
|
6
|
-
@auth = Scrobbler::Auth.new('user')
|
7
|
-
@session = @auth.session('test123token')
|
8
6
|
@event = Scrobbler::Event.new(:id => 328799)
|
9
7
|
end
|
10
8
|
|
@@ -20,9 +18,7 @@ describe Scrobbler::Event do
|
|
20
18
|
end
|
21
19
|
end
|
22
20
|
|
23
|
-
it 'should set user\'s status for
|
24
|
-
@event.attend(@session,1)
|
25
|
-
end
|
21
|
+
it 'should set user\'s status for attendance'
|
26
22
|
|
27
23
|
describe 'events attendees' do
|
28
24
|
before do
|
data/test/unit/tag_spec.rb
CHANGED
@@ -78,7 +78,7 @@ describe Scrobbler::Tag do
|
|
78
78
|
@tag.top_tracks.should be_kind_of(Array)
|
79
79
|
@tag.top_tracks.should have(50).items
|
80
80
|
@tag.top_tracks.first.should be_kind_of(Scrobbler::Track)
|
81
|
-
@tag.top_tracks.first.rank.should eql(1)
|
81
|
+
@tag.top_tracks.first.rank.should eql(1.0)
|
82
82
|
@tag.top_tracks.first.name.should eql('Stayin\' Alive')
|
83
83
|
@tag.top_tracks.first.tagcount.should eql(422)
|
84
84
|
@tag.top_tracks.first.mbid.should eql('')
|
data/test/unit/track_spec.rb
CHANGED
@@ -27,6 +27,7 @@ describe Scrobbler::Track do
|
|
27
27
|
@track.should respond_to(:remove_tag)
|
28
28
|
@track.should respond_to(:search)
|
29
29
|
@track.should respond_to(:share)
|
30
|
+
Scrobbler::Track.should respond_to(:fingerprint_metadata)
|
30
31
|
end
|
31
32
|
|
32
33
|
it 'should be able to add tags'
|
@@ -91,5 +92,14 @@ describe Scrobbler::Track do
|
|
91
92
|
|
92
93
|
it 'should be able to share a track'
|
93
94
|
|
95
|
+
it 'should be able to fetch the metadata that matches a certain finderprint' do
|
96
|
+
@metadata = Scrobbler::Track.fingerprint_metadata('1234')
|
97
|
+
@metadata.should have(5).items
|
98
|
+
@track = @metadata[0]
|
99
|
+
@track.rank.should eql 1.0
|
100
|
+
@track.name.should eql 'Merlin\'s Will'
|
101
|
+
@track.artist.name.should eql 'Ayreon'
|
102
|
+
end
|
103
|
+
|
94
104
|
end
|
95
105
|
|
data/test/unit/user_spec.rb
CHANGED
@@ -206,7 +206,7 @@ describe Scrobbler::User do
|
|
206
206
|
first.name.should eql 'Learning to Live'
|
207
207
|
first.mbid.should eql ''
|
208
208
|
first.playcount.should eql 51
|
209
|
-
first.rank.should eql 1
|
209
|
+
first.rank.should eql 1.0
|
210
210
|
first.url.should eql 'http://www.last.fm/music/Dream+Theater/_/Learning+to+Live'
|
211
211
|
first.image(:small).should eql 'http://userserve-ak.last.fm/serve/34s/12620339.jpg'
|
212
212
|
first.image(:medium).should eql 'http://userserve-ak.last.fm/serve/64s/12620339.jpg'
|
@@ -255,7 +255,7 @@ describe Scrobbler::User do
|
|
255
255
|
first.artist.mbid.should eql 'bc641be9-ca36-4c61-9394-5230433f6646'
|
256
256
|
first.mbid.should eql ''
|
257
257
|
first.playcount.should eql 5
|
258
|
-
first.rank.should eql 1
|
258
|
+
first.rank.should eql 1.0
|
259
259
|
first.url.should eql 'www.last.fm/music/Liquid+Tension+Experiment/_/Three+Minute+Warning'
|
260
260
|
end
|
261
261
|
|
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:
|
4
|
+
hash: 9
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 2.0.
|
9
|
+
- 3
|
10
|
+
version: 2.0.3
|
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-
|
20
|
+
date: 2010-07-20 00:00:00 +02:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
@@ -101,7 +101,7 @@ files:
|
|
101
101
|
- lib/scrobbler.rb
|
102
102
|
- lib/scrobbler/album.rb
|
103
103
|
- lib/scrobbler/artist.rb
|
104
|
-
- lib/scrobbler/
|
104
|
+
- lib/scrobbler/authentication.rb
|
105
105
|
- lib/scrobbler/base.rb
|
106
106
|
- lib/scrobbler/basexml.rb
|
107
107
|
- lib/scrobbler/basexmlinfo.rb
|
@@ -110,42 +110,37 @@ files:
|
|
110
110
|
- lib/scrobbler/helper/image.rb
|
111
111
|
- lib/scrobbler/helper/streamable.rb
|
112
112
|
- lib/scrobbler/library.rb
|
113
|
-
- lib/scrobbler/playing.rb
|
114
113
|
- lib/scrobbler/playlist.rb
|
115
114
|
- lib/scrobbler/radio.rb
|
116
115
|
- lib/scrobbler/rest.rb
|
117
116
|
- lib/scrobbler/session.rb
|
118
117
|
- lib/scrobbler/shout.rb
|
119
|
-
- lib/scrobbler/simpleauth.rb
|
120
118
|
- lib/scrobbler/tag.rb
|
121
119
|
- lib/scrobbler/track.rb
|
122
120
|
- lib/scrobbler/user.rb
|
123
121
|
- lib/scrobbler/venue.rb
|
124
122
|
- tasks/jeweler.rake
|
125
|
-
- tasks/metric_fu.rake
|
126
123
|
- tasks/rdoc.rake
|
127
|
-
- tasks/reek.rake
|
128
|
-
- tasks/roodi.rake
|
129
124
|
- tasks/tests.rake
|
130
125
|
- tasks/yardoc.rake
|
131
|
-
- test/spec_helper.rb
|
132
|
-
- test/unit/library_spec.rb
|
133
|
-
- test/unit/album_spec.rb
|
134
|
-
- test/unit/geo_spec.rb
|
135
|
-
- test/unit/track_spec.rb
|
136
|
-
- test/unit/simpleauth_test.rb
|
137
|
-
- test/unit/auth_spec.rb
|
138
126
|
- test/unit/tag_spec.rb
|
139
|
-
- test/unit/
|
140
|
-
- test/unit/
|
127
|
+
- test/unit/playlist_spec.rb
|
128
|
+
- test/unit/album_spec.rb
|
141
129
|
- test/unit/radio_spec.rb
|
130
|
+
- test/unit/event_spec.rb
|
142
131
|
- test/unit/venue_spec.rb
|
143
|
-
- test/unit/
|
132
|
+
- test/unit/user_spec.rb
|
144
133
|
- test/unit/artist_spec.rb
|
145
134
|
- test/unit/playing_test.rb
|
135
|
+
- test/unit/simpleauth_test.rb
|
136
|
+
- test/unit/geo_spec.rb
|
137
|
+
- test/unit/library_spec.rb
|
138
|
+
- test/unit/track_spec.rb
|
139
|
+
- test/unit/authentication_spec.rb
|
140
|
+
- test/spec_helper.rb
|
141
|
+
- test/test_helper.rb
|
146
142
|
- test/mocks/library.rb
|
147
143
|
- test/mocks/rest.rb
|
148
|
-
- test/test_helper.rb
|
149
144
|
has_rdoc: true
|
150
145
|
homepage: http://github.com/xhochy/scrobbler
|
151
146
|
licenses: []
|
@@ -181,27 +176,27 @@ signing_key:
|
|
181
176
|
specification_version: 3
|
182
177
|
summary: A ruby library for accessing the last.fm v2 webservices
|
183
178
|
test_files:
|
184
|
-
- test/spec_helper.rb
|
185
|
-
- test/unit/library_spec.rb
|
186
|
-
- test/unit/album_spec.rb
|
187
|
-
- test/unit/geo_spec.rb
|
188
|
-
- test/unit/track_spec.rb
|
189
|
-
- test/unit/simpleauth_test.rb
|
190
|
-
- test/unit/auth_spec.rb
|
191
179
|
- test/unit/tag_spec.rb
|
192
|
-
- test/unit/
|
193
|
-
- test/unit/
|
180
|
+
- test/unit/playlist_spec.rb
|
181
|
+
- test/unit/album_spec.rb
|
194
182
|
- test/unit/radio_spec.rb
|
183
|
+
- test/unit/event_spec.rb
|
195
184
|
- test/unit/venue_spec.rb
|
196
|
-
- test/unit/
|
185
|
+
- test/unit/user_spec.rb
|
197
186
|
- test/unit/artist_spec.rb
|
198
187
|
- test/unit/playing_test.rb
|
188
|
+
- test/unit/simpleauth_test.rb
|
189
|
+
- test/unit/geo_spec.rb
|
190
|
+
- test/unit/library_spec.rb
|
191
|
+
- test/unit/track_spec.rb
|
192
|
+
- test/unit/authentication_spec.rb
|
193
|
+
- test/spec_helper.rb
|
194
|
+
- test/test_helper.rb
|
199
195
|
- test/mocks/library.rb
|
200
196
|
- test/mocks/rest.rb
|
201
|
-
- test/test_helper.rb
|
202
|
-
- examples/artist.rb
|
203
197
|
- examples/tag.rb
|
204
|
-
- examples/user.rb
|
205
198
|
- examples/track.rb
|
199
|
+
- examples/user.rb
|
200
|
+
- examples/artist.rb
|
206
201
|
- examples/scrobble.rb
|
207
202
|
- examples/album.rb
|
data/lib/scrobbler/auth.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
module Scrobbler
|
2
|
-
# @todo everything
|
3
|
-
class Auth < Base
|
4
|
-
|
5
|
-
def initialize(username)
|
6
|
-
super()
|
7
|
-
@username = username
|
8
|
-
end
|
9
|
-
|
10
|
-
def session(token)
|
11
|
-
doc = Base.request('auth.getsession', :signed => true, :token => token)
|
12
|
-
asession = {}
|
13
|
-
doc.root.children.each do |child1|
|
14
|
-
next unless child1.name == 'session'
|
15
|
-
child1.children.each do |child2|
|
16
|
-
if child2.name == 'name'
|
17
|
-
asession[:name] = child2.content
|
18
|
-
elsif child2.name == 'key'
|
19
|
-
asession[:key] = child2.content
|
20
|
-
elsif child2.name == 'subscriber'
|
21
|
-
asession[:subscriber] = true if child2.content == '1'
|
22
|
-
asession[:subscriber] = false unless child2.content == '1'
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
Scrobbler::Session.new(asession)
|
27
|
-
end
|
28
|
-
|
29
|
-
def token
|
30
|
-
doc = Base.request('auth.gettoken', :signed => true)
|
31
|
-
stoken = ''
|
32
|
-
doc.root.children.each do |child|
|
33
|
-
next unless child.name == 'token'
|
34
|
-
stoken = child.content
|
35
|
-
end
|
36
|
-
stoken
|
37
|
-
end
|
38
|
-
|
39
|
-
def url(options={})
|
40
|
-
options[:token] = token if options[:token].nil?
|
41
|
-
options[:api_key] = @@api_key
|
42
|
-
"http://www.last.fm/api/auth/?api_key=#{options[:api_key]}&token=#{options[:token]}"
|
43
|
-
end
|
44
|
-
|
45
|
-
def mobile_session
|
46
|
-
# This function require authentication, but SimpleAuth is not yet 2.0
|
47
|
-
raise NotImplementedError
|
48
|
-
end
|
49
|
-
|
50
|
-
def websession
|
51
|
-
# This function require authentication, but SimpleAuth is not yet 2.0
|
52
|
-
raise NotImplementedError
|
53
|
-
end
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
data/lib/scrobbler/playing.rb
DELETED
@@ -1,49 +0,0 @@
|
|
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/simpleauth.rb
DELETED
@@ -1,60 +0,0 @@
|
|
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
|
-
# @todo This is not 2.0!!
|
12
|
-
class SimpleAuth
|
13
|
-
# you should read last.fm/api/submissions#handshake
|
14
|
-
|
15
|
-
attr_accessor :user, :password, :client_id, :client_ver
|
16
|
-
attr_reader :status, :session_id, :now_playing_url, :submission_url
|
17
|
-
|
18
|
-
def initialize(args = {})
|
19
|
-
@user = args[:user] # last.fm username
|
20
|
-
@password = args[:password] # last.fm password
|
21
|
-
@client_id = 'rbs' # Client ID assigned by last.fm; Don't change this!
|
22
|
-
@client_ver = '0.2.13'
|
23
|
-
|
24
|
-
raise ArgumentError, 'Missing required argument' if @user.empty? || @password.empty?
|
25
|
-
|
26
|
-
@connection = REST::Connection.new(AUTH_URL)
|
27
|
-
end
|
28
|
-
|
29
|
-
def handshake!
|
30
|
-
password_hash = Digest::MD5.hexdigest(@password)
|
31
|
-
timestamp = Time.now.to_i.to_s
|
32
|
-
token = Digest::MD5.hexdigest(password_hash + timestamp)
|
33
|
-
|
34
|
-
query = { :hs => 'true',
|
35
|
-
:p => AUTH_VER,
|
36
|
-
:c => @client_id,
|
37
|
-
:v => @client_ver,
|
38
|
-
:u => @user,
|
39
|
-
:t => timestamp,
|
40
|
-
:a => token }
|
41
|
-
result = @connection.get('/', query)
|
42
|
-
|
43
|
-
@status = result.split(/\n/)[0]
|
44
|
-
case @status
|
45
|
-
when /OK/
|
46
|
-
@session_id, @now_playing_url, @submission_url = result.split(/\n/)[1,3]
|
47
|
-
when /BANNED/
|
48
|
-
raise BannedError # something is wrong with the gem, check for an update
|
49
|
-
when /BADAUTH/
|
50
|
-
raise BadAuthError # invalid user/password
|
51
|
-
when /FAILED/
|
52
|
-
raise RequestFailedError, @status
|
53
|
-
when /BADTIME/
|
54
|
-
raise BadTimeError # system time is way off
|
55
|
-
else
|
56
|
-
raise RequestFailedError
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
data/tasks/metric_fu.rake
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require 'metric_fu'
|
3
|
-
MetricFu::Configuration.run do |config|
|
4
|
-
# Deactivated: saikuro, stats, rcov
|
5
|
-
config.metrics = [:churn, :flog, :flay, :reek, :roodi]
|
6
|
-
config.graphs = [:flog, :flay, :reek, :roodi, :rcov]
|
7
|
-
config.flay = { :dirs_to_flay => ['lib'],
|
8
|
-
:minimum_score => 100 }
|
9
|
-
config.flog = { :dirs_to_flog => ['lib'] }
|
10
|
-
config.reek = { :dirs_to_reek => ['lib'] }
|
11
|
-
config.roodi = { :dirs_to_roodi => ['lib'] }
|
12
|
-
config.churn = { :start_date => "1 year ago", :minimum_churn_count => 10}
|
13
|
-
config.rcov = { :environment => 'test',
|
14
|
-
:test_files => ['test/**/*_test.rb',
|
15
|
-
'spec/**/*_spec.rb'],
|
16
|
-
:rcov_opts => ["--sort coverage",
|
17
|
-
"--no-html",
|
18
|
-
"--text-coverage",
|
19
|
-
"--no-color",
|
20
|
-
"--profile",
|
21
|
-
"--rails",
|
22
|
-
"--exclude /gems/,/Library/,spec"]}
|
23
|
-
config.graph_engine = :bluff
|
24
|
-
end
|
25
|
-
rescue LoadError
|
26
|
-
puts "metric_fu not available. Install it with: gem install metric_fu"
|
27
|
-
end
|
data/tasks/reek.rake
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require 'reek/rake/task'
|
3
|
-
Reek::Rake::Task.new do |t|
|
4
|
-
t.fail_on_error = true
|
5
|
-
t.verbose = false
|
6
|
-
t.source_files = 'lib/**/*.rb'
|
7
|
-
end
|
8
|
-
rescue LoadError
|
9
|
-
task :reek do
|
10
|
-
abort "Reek is not available. In order to run reek, you must: sudo gem install reek"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
data/tasks/roodi.rake
DELETED
data/test/unit/auth_spec.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
-
|
3
|
-
describe Scrobbler::Auth do
|
4
|
-
|
5
|
-
before(:all) do
|
6
|
-
@auth = Scrobbler::Auth.new('user')
|
7
|
-
end
|
8
|
-
|
9
|
-
it 'should implement all methods from the Last.fm 2.0 API' do
|
10
|
-
@auth.should respond_to(:mobile_session)
|
11
|
-
@auth.should respond_to(:session)
|
12
|
-
@auth.should respond_to(:token)
|
13
|
-
@auth.should respond_to(:websession)
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'should be able to start a mobile session'
|
17
|
-
|
18
|
-
it 'should be able to fetch a session key' do
|
19
|
-
session = @auth.session('test123token')
|
20
|
-
session.should be_kind_of(Scrobbler::Session)
|
21
|
-
session.name.should eql('MyLastFMUsername')
|
22
|
-
session.key.should eql('d580d57f32848f5dcf574d1ce18d78b2')
|
23
|
-
session.subscriber.should be_false
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'should be able to fetch a request token' do
|
27
|
-
@auth.token.should eql('0e6af5cd2fff6b314994af5b0c58ecc1')
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'should be able to start a web session'
|
31
|
-
|
32
|
-
it 'should be able to get a url for authenticate this service' do
|
33
|
-
@auth.url.should eql('http://www.last.fm/api/auth/?api_key=foo123&token=0e6af5cd2fff6b314994af5b0c58ecc1')
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|