rdio 0.0.96 → 0.0.98b

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/README CHANGED
@@ -1,4 +1,4 @@
1
- -*- outline -*-
1
+ -*- org -*-
2
2
 
3
3
  * ABOUT
4
4
 
@@ -35,7 +35,7 @@ variables to the appropriate values:
35
35
  RDIO_KEY
36
36
  RDIO_SECRET
37
37
 
38
- You must also serialize an authrozied access token to the file
38
+ There is a sample .rc file in dot-rdio. You must also serialize an authorized access token to the file
39
39
  .rdio_access_token. This can be done with:
40
40
 
41
41
  make .rdio_access_token
@@ -44,3 +44,11 @@ You must also serialize an authrozied access token to the file
44
44
 
45
45
  ./create_access_token
46
46
 
47
+ There is a sample in dot-rdio_access_token.
48
+
49
+ * CONTRIBUTORS
50
+
51
+ Thanks for the pull requests that have been merged to the following:
52
+
53
+ - Scott Hyndman ( https://github.com/shyndman )
54
+ - Rick Fletcher ( https://github.com/rfletcher )
@@ -20,6 +20,17 @@ module Rdio
20
20
  attr_accessor :log_methods
21
21
  attr_accessor :log_symbols
22
22
  attr_accessor :log_posts
23
+ attr_accessor :log_fill
24
+ #
25
+ # Specific setting to turn off warnings like the following:
26
+ #
27
+ # Couldn't find symbol: radio_key => rr31531 for type: Rdio::Artist
28
+ #
29
+ # during tests, because we see it constantly and isn't really a
30
+ # problem. By default it is true, but it is turned off for all
31
+ # tests.
32
+ attr_accessor :log_couldnt_find_symbols
33
+
23
34
  def log(str)
24
35
  logger.debug { str }
25
36
  end
@@ -29,6 +40,8 @@ module Rdio
29
40
  self.log_methods = false
30
41
  self.log_symbols = false
31
42
  self.log_posts = false
43
+ self.log_couldnt_find_symbols = false
44
+ self.log_fill = false
32
45
 
33
46
  @logger ||= ::Logger.new(STDERR)
34
47
  @api = nil
@@ -89,7 +102,11 @@ require 'rdio/datatypes'
89
102
  require 'rdio/types'
90
103
  require 'rdio/call'
91
104
 
92
- # Silly syntax so you can say Rd::io...blah...blah...blah
105
+ # simple additions
106
+ require 'rdio/simple_om'
107
+ require 'rdio/simple_rdio'
108
+
109
+ # Silly syntax so you can say Rd::io.<method>
93
110
  module Rd
94
111
 
95
112
  # Returns the shared Rdio::Api instance from Rdio::api
@@ -148,7 +148,17 @@ module Rdio
148
148
 
149
149
  def fill(x)
150
150
  return self if not x
151
+ if Rdio::log_fill
152
+ Rdio::log "#{self.class}.fill #{x.class} : #{x}"
153
+ end
151
154
  syms_to_types = Rdio::symbols_to_types || {}
155
+ #
156
+ # https://github.com/spudtrooper/rdiorb/issues/9: Certain rubys
157
+ # don't declare 'each' on String. In this case and others where
158
+ # the key is a mapped type and the resulting body isn't a Hash,
159
+ # make x a Hash
160
+ #
161
+ x = {x => nil} if not x.is_a? Hash
152
162
  x.each do |k,v|
153
163
  sym = Rdio::camel2underscores(k).to_sym
154
164
  #
@@ -158,9 +168,9 @@ module Rdio
158
168
  #
159
169
  type = syms_to_types[sym]
160
170
  if Rdio::log_symbols
161
- Rdio::log "#{self.class}.#{sym} => #{type}"
171
+ Rdio::log "#{self.class}.#{sym} => #{type} v=#{v.class}"
162
172
  end
163
- if type
173
+ if type and v.is_a? Enumerable
164
174
  #
165
175
  # Allow simple types that are used for arrays
166
176
  #
@@ -177,8 +187,10 @@ module Rdio
177
187
  sym_eq = (Rdio::camel2underscores(k)+'=').to_sym
178
188
  self.send sym_eq,o
179
189
  rescue Exception => e
180
- Rdio::logger.warn "Couldn't find symbol: " +
181
- "#{sym} => #{o} for type: #{self.class}"
190
+ if Rdio::log_couldnt_find_symbols
191
+ Rdio::logger.warn "Couldn't find symbol: " +
192
+ "#{sym} => #{o} for type: #{self.class}"
193
+ end
182
194
  end
183
195
  end
184
196
  self
@@ -297,7 +309,15 @@ module Rdio
297
309
  if Rdio::log_posts
298
310
  Rdio::log "Post to url=#{url} method=#{method} args=#{args}"
299
311
  end
312
+ #
313
+ # For backwards compatibility the response may have a 'body'
314
+ # attribute or a tuple could be returned. Handle both cases.
315
+ #
300
316
  resp,data = access_token(requires_auth).post url,new_args
317
+ begin
318
+ return resp.body
319
+ rescue
320
+ end
301
321
  return data
302
322
  end
303
323
 
@@ -32,9 +32,9 @@ module Rdio
32
32
  require 'launchy'
33
33
  Launchy.open url
34
34
  rescue Exception => e
35
- Rdio::log.error e
36
- Rdio::log.info 'Install the \'launchy\' gem to avoid this error'
37
- Rdio::log.info 'Trying system \'open\''
35
+ Rdio::logger.error e
36
+ Rdio::logger.info 'Install the \'launchy\' gem to avoid this error'
37
+ Rdio::logger.info 'Trying system \'open\''
38
38
  system 'open',url
39
39
  end
40
40
 
@@ -0,0 +1,151 @@
1
+ # om is oauth-mini - a simple implementation of a useful subset of OAuth.
2
+ # It's designed to be useful and reusable but not general purpose.
3
+ #
4
+ # (c) 2011 Rdio Inc
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ # A simple OAuth client implementation. Do less better.
24
+ # Here are the restrictions:
25
+ # - only HMAC-SHA1 is supported
26
+ # - only WWW-Authentiate form signatures are generated
27
+ #
28
+ # To sign a request:
29
+ # auth = om([consumer_key,consumer_secret], url, params)
30
+ # send Authorization: <auth>
31
+ # when POSTing <params> to <url>
32
+ # Optional additional arguments are:
33
+ # token = [oauth_token, oauth_token_secret]
34
+ # method = "POST"
35
+ # realm = "Realm-for-authorization-header"
36
+ #
37
+ # Changes by jeff@jeffpalm.com:
38
+ #
39
+ # - added module Rdio
40
+ #
41
+
42
+ require 'uri'
43
+ require 'cgi'
44
+ require 'digest'
45
+ require 'digest/sha1'
46
+
47
+ module Rdio
48
+
49
+ class OM
50
+
51
+ def self.om(consumer, url, post_params, token=nil, method='POST', realm=nil)
52
+ # A one-shot simple OAuth signature generator
53
+
54
+ # the method must be upper-case
55
+ method.upcase!
56
+
57
+ # we want params as an Array of name / value pairs
58
+ if post_params.is_a?(Array)
59
+ params = post_params
60
+ else
61
+ params = post_params.collect
62
+ end
63
+
64
+ # normalize the URL
65
+ url = URI.parse(url)
66
+ # scheme is lower-case
67
+ url.scheme = url.scheme.downcase
68
+ # remove username & password
69
+ url.user = url.password = nil
70
+ # host is lowercase
71
+ url.host.downcase!
72
+
73
+ # add URL params to the params
74
+ if url.query
75
+ CGI.parse(url.query).each { |k,vs| vs.each { |v| params.push([k,v]) } }
76
+ end
77
+
78
+ # remove the params and fragment
79
+ url.query = nil
80
+ url.fragment = nil
81
+
82
+ # add OAuth params
83
+ params = params + [
84
+ ['oauth_version', '1.0'],
85
+ ['oauth_timestamp', Time.now.to_i.to_s],
86
+ ['oauth_nonce', rand(1000000).to_s],
87
+ ['oauth_signature_method', 'HMAC-SHA1'],
88
+ ['oauth_consumer_key', consumer[0]],
89
+ ]
90
+
91
+ # the consumer secret is the first half of the HMAC-SHA1 key
92
+ hmac_key = consumer[1] + '&'
93
+
94
+ if token != nil
95
+ # include a token in params
96
+ params.push ['oauth_token', token[0]]
97
+ # and the token secret in the HMAC-SHA1 key
98
+ hmac_key += token[1]
99
+ end
100
+
101
+ # Sort lexicographically, first after key, then after value.
102
+ params.sort!
103
+ # escape the key/value pairs and combine them into a string
104
+ normalized_params = (params.collect {|p| percent_encode(p[0])+'='+percent_encode(p[1])}).join '&'
105
+
106
+ # build the signature base string
107
+ signature_base_string = (percent_encode(method) +
108
+ '&' + percent_encode(url.to_s) +
109
+ '&' + percent_encode(normalized_params))
110
+
111
+ # HMAC-SHA1
112
+ hmac = Digest::HMAC.new(hmac_key, Digest::SHA1)
113
+ hmac.update(signature_base_string)
114
+
115
+ # Calculate the digest base 64. Drop the trailing \n
116
+ oauth_signature = [hmac.digest].pack('m0').strip
117
+
118
+ # Build the Authorization header
119
+ if realm
120
+ authorization_params = [['realm', realm]]
121
+ else
122
+ authorization_params = []
123
+ end
124
+ authorization_params.push(['oauth_signature', oauth_signature])
125
+
126
+ # we only want certain params in the auth header
127
+ oauth_params = ['oauth_version', 'oauth_timestamp', 'oauth_nonce',
128
+ 'oauth_signature_method', 'oauth_signature',
129
+ 'oauth_consumer_key', 'oauth_token']
130
+ authorization_params.concat(params.select { |param| nil != oauth_params.index(param[0]) })
131
+
132
+ return 'OAuth ' + (authorization_params.collect {|param| '%s="%s"' % param}).join(', ')
133
+ end
134
+
135
+ def self.percent_encode(s)
136
+ chars = s.chars.map do |c|
137
+ if ((c >= '0' and c <= '9') or
138
+ (c >= 'A' and c <= 'Z') or
139
+ (c >= 'a' and c <= 'z') or
140
+ c == '-' or c == '.' or c == '_' or c == '~')
141
+ c
142
+ else
143
+ '%%%02X' % c[0]
144
+ end
145
+ end
146
+ chars.join
147
+ end
148
+
149
+ end
150
+
151
+ end
@@ -0,0 +1,87 @@
1
+ # (c) 2011 Rdio Inc
2
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
3
+ # of this software and associated documentation files (the "Software"), to deal
4
+ # in the Software without restriction, including without limitation the rights
5
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6
+ # copies of the Software, and to permit persons to whom the Software is
7
+ # furnished to do so, subject to the following conditions:
8
+ #
9
+ # The above copyright notice and this permission notice shall be included in
10
+ # all copies or substantial portions of the Software.
11
+ #
12
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
18
+ # THE SOFTWARE.
19
+ #
20
+ # Changes by jeff@jeffpalm.com:
21
+ #
22
+ # - added module Rdio
23
+ # - changed class named from Rdio to SimpleRdio
24
+ #
25
+
26
+ require 'uri'
27
+ require 'net/http'
28
+ require 'cgi'
29
+ require 'json'
30
+
31
+ module Rdio
32
+
33
+ class SimpleRdio
34
+ # the consumer and token can be accessed
35
+ attr_accessor :consumer, :token
36
+
37
+ def initialize(consumer, token=nil)
38
+ @consumer = consumer
39
+ @token = token
40
+ end
41
+
42
+ def begin_authentication(callback_url)
43
+ # request a request token from the server
44
+ response = signed_post('http://api.rdio.com/oauth/request_token',
45
+ {'oauth_callback' => callback_url})
46
+ # parse the response
47
+ parsed = CGI.parse(response)
48
+ # save the token
49
+ @token = [parsed['oauth_token'][0], parsed['oauth_token_secret'][0]]
50
+ # return an URL that the user can use to authorize this application
51
+ return parsed['login_url'][0] + '?oauth_token=' + parsed['oauth_token'][0]
52
+ end
53
+
54
+ def complete_authentication(verifier)
55
+ # request an access token
56
+ response = signed_post('http://api.rdio.com/oauth/access_token',
57
+ {'oauth_verifier' => verifier})
58
+ # parse the response
59
+ parsed = CGI.parse(response)
60
+ # save the token
61
+ @token = [parsed['oauth_token'][0], parsed['oauth_token_secret'][0]]
62
+ end
63
+
64
+ def call(method, params={})
65
+ # make a copy of the dict
66
+ params = params.clone
67
+ # put the method in the dict
68
+ params['method'] = method
69
+ # call to the server and parse the response
70
+ return JSON.load(signed_post('http://api.rdio.com/1/', params))
71
+ end
72
+
73
+ private
74
+
75
+ def signed_post(url, params)
76
+ auth = OM::om(@consumer, url, params, @token)
77
+ url = URI.parse(url)
78
+ http = Net::HTTP.new(url.host, url.port)
79
+ req = Net::HTTP::Post.new(url.path, {'Authorization' => auth})
80
+ req.set_form_data(params)
81
+ res = http.request(req)
82
+ return res.body
83
+ end
84
+
85
+ end
86
+
87
+ end
@@ -30,7 +30,7 @@ module Rdio
30
30
 
31
31
  attr_accessor :album_keys
32
32
 
33
- # Returns an array of Album for the query and other params
33
+ # Returns an array of Artist for the query and other params
34
34
  def self.search(query,never_or=nil,extras=nil,start=nil,count=nil)
35
35
  extras = Rdio::add_to_array extras,'artists'
36
36
  Search.search query,Artist,never_or,extras,start,count
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rdio
3
3
  version: !ruby/object:Gem::Version
4
- hash: 223
5
- prerelease:
4
+ hash: 419
5
+ prerelease: 6
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 96
10
- version: 0.0.96
9
+ - 98
10
+ - b
11
+ version: 0.0.98b
11
12
  platform: ruby
12
13
  authors:
13
14
  - Jeffrey Palm
@@ -15,7 +16,7 @@ autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2011-08-15 00:00:00 Z
19
+ date: 2012-03-03 00:00:00 Z
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: oauth
@@ -52,6 +53,8 @@ files:
52
53
  - lib/rdio/datatypes.rb
53
54
  - lib/rdio/types.rb
54
55
  - lib/rdio/call.rb
56
+ - lib/rdio/simple_om.rb
57
+ - lib/rdio/simple_rdio.rb
55
58
  homepage: http://github.com/spudtrooper/rdiorb
56
59
  licenses: []
57
60
 
@@ -72,15 +75,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
72
75
  required_rubygems_version: !ruby/object:Gem::Requirement
73
76
  none: false
74
77
  requirements:
75
- - - ">="
78
+ - - ">"
76
79
  - !ruby/object:Gem::Version
77
- hash: 3
80
+ hash: 25
78
81
  segments:
79
- - 0
80
- version: "0"
82
+ - 1
83
+ - 3
84
+ - 1
85
+ version: 1.3.1
81
86
  requirements:
82
87
  - launchy gem to use authorized calls
83
- rubyforge_project: "%NAME"
88
+ rubyforge_project: rdio
84
89
  rubygems_version: 1.8.6
85
90
  signing_key:
86
91
  specification_version: 2