rscrobbler 0.0.2 → 0.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.
@@ -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: