rscrobbler 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rscrobbler'
4
+
5
+ begin
6
+ print "Last.fm username: "
7
+ LastFM.username = STDIN.gets.strip
8
+
9
+ print "Last.fm password: "
10
+ system "stty -echo"
11
+ puts "\nYour Last.fm auth token: #{LastFM.generate_auth_token(STDIN.gets.strip)}"
12
+ system "stty echo"
13
+ rescue NoMethodError, Interrupt
14
+ system "stty echo"
15
+ exit
16
+ end
data/lib/rscrobbler.rb CHANGED
@@ -1,161 +1,161 @@
1
- require 'digest/md5'
2
- require 'libxml'
3
- require 'net/http'
4
- require 'uri'
5
-
6
- $:.unshift(File.dirname(__FILE__))
7
-
8
- require 'lastfm/album'
9
- require 'lastfm/artist'
10
- require 'lastfm/auth'
11
- require 'lastfm/chart'
12
- require 'lastfm/event'
13
- require 'lastfm/geo'
14
- require 'lastfm/group'
15
- require 'lastfm/library'
16
- require 'lastfm/playlist'
17
- require 'lastfm/radio'
18
- require 'lastfm/tag'
19
- require 'lastfm/tasteometer'
20
- require 'lastfm/track'
21
- require 'lastfm/user'
22
- require 'lastfm/venue'
23
-
24
- module LastFM
25
- VERSION = '0.0.2'
26
-
27
- HOST = 'ws.audioscrobbler.com'
28
- POST_URI = URI.parse("http://#{HOST}/2.0/")
29
-
30
- class RequestError < StandardError; end
31
- class AuthenticationError < StandardError; end
32
-
33
- class << self
34
-
35
- attr_accessor :api_key, :api_secret, :username, :auth_token
36
- attr_reader :session_key, :logger
37
-
38
- # Authenticate the service with provided login credentials. Use mobile
39
- # authentication to avoid redirecting to the website to log in.
40
- #
41
- # @see http://www.last.fm/api/authspec last.fm auth spec
42
- # @return [String] session key provided from authentication
43
- def authenticate!
44
- %w[api_key api_secret username auth_token].each do |cred|
45
- raise AuthenticationError, "Missing credential: #{cred}" unless LastFM.send(cred)
46
- end
47
- @session_key = Auth.get_mobile_session( username, auth_token ).find_first('session/key').content
48
- end
49
-
50
- # Has the service been authenticated?
51
- #
52
- # @return [Boolean] whether the service has been authenticated
53
- def authenticated?
54
- !!session_key
55
- end
56
-
57
- # Ensure the service has been authenticated; raise an error if it hasn't.
58
- #
59
- # @raise [AuthenticationError] if the service hasn't been authenticated.
60
- def requires_authentication
61
- raise AuthenticationError, 'LastFM Authentication Required' unless authenticated?
62
- end
63
-
64
- # Generate auth token from username and given password.
65
- #
66
- # @param [String] password password to use
67
- # @return [String] md5 digest of the username and password
68
- def generate_auth_token( password )
69
- self.auth_token = Digest::MD5.hexdigest( username.dup << Digest::MD5.hexdigest(password) )
70
- end
71
-
72
- # Construct an HTTP GET call from params, and load the response into a LibXML Document.
73
- #
74
- # @param [String] method last.fm api method to call
75
- # @param [optional, Boolean] secure whether sign the request with a method signature and session key
76
- # (one exception being auth methods, which require a method signature but no session key)
77
- # @param [Hash] params parameters to send, excluding method, api_key, api_sig, and sk
78
- # @return [LibXML::XML::Document] xml document of the data contained in the response
79
- # @raise [LastFMError] if the request fails
80
- def get( method, secure = false, params = {} )
81
- path = generate_path(method, secure, params)
82
- logger.debug( "Last.fm HTTP GET: #{HOST+path}" ) if logger
83
- response = Net::HTTP.get_response( HOST, path )
84
- check_status( LibXML::XML::Parser.string( response.body ).parse )
85
- end
86
-
87
- # Construct an HTTP POST call from params, and check the response status.
88
- #
89
- # @param [String] method last.fm api method to call
90
- # @param [Hash] params parameters to send, excluding method, api_key, api_sig, and sk
91
- # @return [LibXML::XML::Document] xml document of the data contained in the response
92
- # @raise [LastFMError] if the request fails
93
- def post( method, params )
94
- params = construct_params( method, :secure, params )
95
- logger.debug( "Last.fm HTTP POST: #{POST_URI}, #{params.to_s}" ) if logger
96
- response = Net::HTTP.post_form( POST_URI, params )
97
- check_status( LibXML::XML::Parser.string( response.body ).parse )
98
- end
99
-
100
- private
101
-
102
- # Check an XML document for status = failed, and throw a descriptive error if it's found.
103
- #
104
- # @param [LibXML::XML::Document] xml xml document to check for errors
105
- # @return [LibXML::XML::Document] the xml document if no errors were found
106
- # @raise [LastFMError] if an error is found
107
- # @private
108
- def check_status( xml )
109
- raise RequestError, xml.find_first('error').content if xml.root.attributes['status'] == 'failed'
110
- xml
111
- end
112
-
113
- # Normalize the parameter list by converting values to a string and removing any nils. Add method,
114
- # api key, session key, and api signature parameters where necessary.
115
- #
116
- # @param [String] method last.fm api method
117
- # @param [Boolean] secure whether to include session key and api signature in the parameters
118
- # @param [Hash] params parameters to normalize and add to
119
- # @return [Hash] complete, normalized parameters
120
- def construct_params( method, secure, params )
121
- params.delete_if{|k,v| v.nil? }
122
- params.each{|k,v| params[k] = params[k].to_s }
123
- params['method'] = method
124
- params['api_key'] = api_key
125
- params['sk'] = session_key if authenticated? && secure
126
- params['api_sig'] = generate_method_signature( params ) if secure
127
- params
128
- end
129
-
130
- # Generate the path for a particular method call given params.
131
- #
132
- # @param [String] method last.fm method to call
133
- # @param [Boolean] secure whether to include session key and api signature in the call
134
- # @param [optional, Hash] params parameters to include in the api call
135
- # @return [String] path for the api call
136
- # @private
137
- def generate_path( method, secure, params={} )
138
- params = construct_params( method, secure, params )
139
- url = "/2.0/?method=#{params.delete('method')}"
140
- params.keys.each do |key|
141
- url << "&#{key}=#{params[key]}"
142
- end
143
- URI.encode(url)
144
- end
145
-
146
- # Generate a method signature based on given parameters.
147
- #
148
- # @param [Hash] parameters to combine into a method signature
149
- # @return [String] method signature based on all the parameters
150
- # @see http://www.last.fm/api/authspec#8
151
- # @private
152
- def generate_method_signature( params )
153
- str = ''
154
- params.keys.sort.each do |key|
155
- str << key << params[key]
156
- end
157
- Digest::MD5.hexdigest( str << api_secret )
158
- end
159
-
160
- end
161
- end
1
+ require 'digest/md5'
2
+ require 'libxml'
3
+ require 'net/http'
4
+ require 'uri'
5
+
6
+ $:.unshift(File.dirname(__FILE__))
7
+
8
+ require 'lastfm/album'
9
+ require 'lastfm/artist'
10
+ require 'lastfm/auth'
11
+ require 'lastfm/chart'
12
+ require 'lastfm/event'
13
+ require 'lastfm/geo'
14
+ require 'lastfm/group'
15
+ require 'lastfm/library'
16
+ require 'lastfm/playlist'
17
+ require 'lastfm/radio'
18
+ require 'lastfm/tag'
19
+ require 'lastfm/tasteometer'
20
+ require 'lastfm/track'
21
+ require 'lastfm/user'
22
+ require 'lastfm/venue'
23
+
24
+ module LastFM
25
+ VERSION = '0.0.3'
26
+
27
+ HOST = 'ws.audioscrobbler.com'
28
+ POST_URI = URI.parse("http://#{HOST}/2.0/")
29
+
30
+ class RequestError < StandardError; end
31
+ class AuthenticationError < StandardError; end
32
+
33
+ class << self
34
+
35
+ attr_accessor :api_key, :api_secret, :username, :auth_token
36
+ attr_reader :session_key, :logger
37
+
38
+ # Authenticate the service with provided login credentials. Use mobile
39
+ # authentication to avoid redirecting to the website to log in.
40
+ #
41
+ # @see http://www.last.fm/api/authspec last.fm auth spec
42
+ # @return [String] session key provided from authentication
43
+ def authenticate!
44
+ [:api_key, :api_secret, :username, :auth_token].each do |cred|
45
+ raise AuthenticationError, "Missing credential: #{cred}" unless LastFM.send(cred)
46
+ end
47
+ @session_key = Auth.get_mobile_session( username, auth_token ).find_first('session/key').content
48
+ end
49
+
50
+ # Has the service been authenticated?
51
+ #
52
+ # @return [Boolean] whether the service has been authenticated
53
+ def authenticated?
54
+ !!session_key
55
+ end
56
+
57
+ # Ensure the service has been authenticated; raise an error if it hasn't.
58
+ #
59
+ # @raise [AuthenticationError] if the service hasn't been authenticated.
60
+ def requires_authentication
61
+ raise AuthenticationError, 'LastFM Authentication Required' unless authenticated?
62
+ end
63
+
64
+ # Generate auth token from username and given password.
65
+ #
66
+ # @param [String] password password to use
67
+ # @return [String] md5 digest of the username and password
68
+ def generate_auth_token( password )
69
+ self.auth_token = Digest::MD5.hexdigest( username.dup << Digest::MD5.hexdigest(password) )
70
+ end
71
+
72
+ # Construct an HTTP GET call from params, and load the response into a LibXML Document.
73
+ #
74
+ # @param [String] method last.fm api method to call
75
+ # @param [optional, Boolean] secure whether sign the request with a method signature and session key
76
+ # (one exception being auth methods, which require a method signature but no session key)
77
+ # @param [Hash] params parameters to send, excluding method, api_key, api_sig, and sk
78
+ # @return [LibXML::XML::Document] xml document of the data contained in the response
79
+ # @raise [LastFMError] if the request fails
80
+ def get( method, secure = false, params = {} )
81
+ path = generate_path(method, secure, params)
82
+ logger.debug( "Last.fm HTTP GET: #{HOST+path}" ) if logger
83
+ response = Net::HTTP.get_response( HOST, path )
84
+ check_status( LibXML::XML::Parser.string( response.body ).parse )
85
+ end
86
+
87
+ # Construct an HTTP POST call from params, and check the response status.
88
+ #
89
+ # @param [String] method last.fm api method to call
90
+ # @param [Hash] params parameters to send, excluding method, api_key, api_sig, and sk
91
+ # @return [LibXML::XML::Document] xml document of the data contained in the response
92
+ # @raise [LastFMError] if the request fails
93
+ def post( method, params )
94
+ params = construct_params( method, :secure, params )
95
+ logger.debug( "Last.fm HTTP POST: #{POST_URI}, #{params.to_s}" ) if logger
96
+ response = Net::HTTP.post_form( POST_URI, params )
97
+ check_status( LibXML::XML::Parser.string( response.body ).parse )
98
+ end
99
+
100
+ private
101
+
102
+ # Check an XML document for status = failed, and throw a descriptive error if it's found.
103
+ #
104
+ # @param [LibXML::XML::Document] xml xml document to check for errors
105
+ # @return [LibXML::XML::Document] the xml document if no errors were found
106
+ # @raise [LastFMError] if an error is found
107
+ # @private
108
+ def check_status( xml )
109
+ raise RequestError, xml.find_first('error').content if xml.root.attributes['status'] == 'failed'
110
+ xml
111
+ end
112
+
113
+ # Normalize the parameter list by converting values to a string and removing any nils. Add method,
114
+ # api key, session key, and api signature parameters where necessary.
115
+ #
116
+ # @param [String] method last.fm api method
117
+ # @param [Boolean] secure whether to include session key and api signature in the parameters
118
+ # @param [Hash] params parameters to normalize and add to
119
+ # @return [Hash] complete, normalized parameters
120
+ def construct_params( method, secure, params )
121
+ params.delete_if{|k,v| v.nil? }
122
+ params.each{|k,v| params[k] = params[k].to_s }
123
+ params['method'] = method
124
+ params['api_key'] = api_key
125
+ params['sk'] = session_key if authenticated? && secure
126
+ params['api_sig'] = generate_method_signature( params ) if secure
127
+ params
128
+ end
129
+
130
+ # Generate the path for a particular method call given params.
131
+ #
132
+ # @param [String] method last.fm method to call
133
+ # @param [Boolean] secure whether to include session key and api signature in the call
134
+ # @param [optional, Hash] params parameters to include in the api call
135
+ # @return [String] path for the api call
136
+ # @private
137
+ def generate_path( method, secure, params={} )
138
+ params = construct_params( method, secure, params )
139
+ url = "/2.0/?method=#{params.delete('method')}"
140
+ params.keys.each do |key|
141
+ url << "&#{key}=#{params[key]}"
142
+ end
143
+ URI.encode(url)
144
+ end
145
+
146
+ # Generate a method signature based on given parameters.
147
+ #
148
+ # @param [Hash] parameters to combine into a method signature
149
+ # @return [String] method signature based on all the parameters
150
+ # @see http://www.last.fm/api/authspec#8
151
+ # @private
152
+ def generate_method_signature( params )
153
+ str = ''
154
+ params.keys.sort.each do |key|
155
+ str << key << params[key]
156
+ end
157
+ Digest::MD5.hexdigest( str << api_secret )
158
+ end
159
+
160
+ end
161
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rscrobbler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-10-25 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: libxml-ruby
16
- requirement: &2165660740 !ruby/object:Gem::Requirement
16
+ requirement: &2153707780 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,11 +21,12 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2165660740
24
+ version_requirements: *2153707780
25
25
  description: rscrobbler is a Ruby gem for accessing Last.fm's API (http://www.last.fm/api).
26
26
  email:
27
27
  - sgt.floydpepper@gmail.com
28
- executables: []
28
+ executables:
29
+ - generate_lastfm_auth_token
29
30
  extensions: []
30
31
  extra_rdoc_files: []
31
32
  files:
@@ -45,6 +46,7 @@ files:
45
46
  - lib/lastfm/user.rb
46
47
  - lib/lastfm/venue.rb
47
48
  - lib/rscrobbler.rb
49
+ - bin/generate_lastfm_auth_token
48
50
  homepage: https://github.com/sgtFloyd/rscrobbler
49
51
  licenses: []
50
52
  post_install_message: