napster 0.0.0 → 0.1.0
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.
- checksums.yaml +4 -4
- data/.gitignore +39 -5
- data/.rubocop.yml +4 -0
- data/README.md +336 -8
- data/Rakefile +3 -3
- data/bin/console +3 -3
- data/lib/napster.rb +27 -4
- data/lib/napster/client.rb +276 -0
- data/lib/napster/me.rb +58 -0
- data/lib/napster/models/album.rb +97 -0
- data/lib/napster/models/artist.rb +93 -0
- data/lib/napster/models/chart.rb +34 -0
- data/lib/napster/models/content.rb +28 -0
- data/lib/napster/models/favorite.rb +130 -0
- data/lib/napster/models/favorite_status.rb +34 -0
- data/lib/napster/models/follower.rb +39 -0
- data/lib/napster/models/following.rb +62 -0
- data/lib/napster/models/library.rb +136 -0
- data/lib/napster/models/library_date_time.rb +33 -0
- data/lib/napster/models/member.rb +124 -0
- data/lib/napster/models/playlist.rb +279 -0
- data/lib/napster/models/profile.rb +75 -0
- data/lib/napster/models/tag.rb +74 -0
- data/lib/napster/models/track.rb +72 -0
- data/lib/napster/models/uploaded_image.rb +36 -0
- data/lib/napster/moniker.rb +29 -0
- data/lib/napster/request.rb +24 -0
- data/lib/napster/response_error.rb +14 -0
- data/lib/napster/version.rb +1 -1
- data/lib/string_helper.rb +10 -0
- data/napster.gemspec +30 -17
- metadata +132 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f53597ca1c82bbe5dfdff89de0e2430077ff4c9
|
4
|
+
data.tar.gz: ac674709f442f4de9b040bad17ca6021766533c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7e5b49b0b9990cad7a882d29dfa086a9a9647622c930ae80c92ed6456f40950ec9d1ccfed09ec22c75037328c5b32652c0a89aa94ab1d3ab8e7b030e9086399
|
7
|
+
data.tar.gz: 5b7a4b1e5b93c1f727db9262c2a5ed10e7052500e3ccec7740ec9133fa1420229a9df487eaaa92736985acdefe22a788d31d118fc71766d63d7825efbefbb84b
|
data/.gitignore
CHANGED
@@ -1,9 +1,43 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
*.gem
|
2
|
+
*.lock
|
3
|
+
*.rbc
|
4
|
+
/.config
|
5
5
|
/coverage/
|
6
|
-
/
|
6
|
+
/InstalledFiles
|
7
7
|
/pkg/
|
8
8
|
/spec/reports/
|
9
|
+
/spec/examples.txt
|
10
|
+
/test/tmp/
|
11
|
+
/test/version_tmp/
|
9
12
|
/tmp/
|
13
|
+
|
14
|
+
## Specific to RubyMotion:
|
15
|
+
.dat*
|
16
|
+
.repl_history
|
17
|
+
build/
|
18
|
+
|
19
|
+
## Documentation cache and generated files:
|
20
|
+
/.yardoc/
|
21
|
+
/_yardoc/
|
22
|
+
/doc/
|
23
|
+
/rdoc/
|
24
|
+
|
25
|
+
## Environment normalization:
|
26
|
+
/.bundle/
|
27
|
+
/vendor/bundle
|
28
|
+
/lib/bundler/man/
|
29
|
+
|
30
|
+
# for a library or gem, you might want to ignore these files since the code is
|
31
|
+
# intended to run in multiple environments; otherwise, check them in:
|
32
|
+
# Gemfile.lock
|
33
|
+
# .ruby-version
|
34
|
+
# .ruby-gemset
|
35
|
+
|
36
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
37
|
+
.rvmrc
|
38
|
+
|
39
|
+
## Configs
|
40
|
+
spec/config.yml
|
41
|
+
|
42
|
+
## RBENV related
|
43
|
+
.ruby-version
|
data/.rubocop.yml
ADDED
data/README.md
CHANGED
@@ -1,8 +1,19 @@
|
|
1
|
-
|
1
|
+
<!-- TODO: Move this SVG to Dev Portal assets when we have more assets. Right now it's in Dropbox :) -->
|
2
|
+
<a href="http://developer.napster.com/">
|
3
|
+
<img src="https://dl.dropboxusercontent.com/s/bfydqpzisetm7y3/napster.svg?dl=0" alt="Napster Logo" title="Napster API" align="right" width=150 height=150/>
|
4
|
+
</a>
|
2
5
|
|
3
|
-
|
6
|
+
<!--
|
7
|
+
Put Badges here when we have them:
|
8
|
+
[
|
9
|
+
-->
|
10
|
+
<!--
|
11
|
+
TODO: Add this link to the top when we change name of Google Forum
|
12
|
+
**Got a question?** Let us know via the Napster API [google forum](https://groups.google.com/forum/#!forum/rhapsody-api).
|
13
|
+
-->
|
14
|
+
# Napster Gem
|
4
15
|
|
5
|
-
|
16
|
+
A Ruby interface to the [Napster API](https://developer.napster.com/).
|
6
17
|
|
7
18
|
## Installation
|
8
19
|
|
@@ -20,22 +31,339 @@ Or install it yourself as:
|
|
20
31
|
|
21
32
|
$ gem install napster
|
22
33
|
|
34
|
+
### Ruby version
|
35
|
+
|
36
|
+
Ruby version should be 2.0 or greater.
|
37
|
+
|
23
38
|
## Usage
|
24
39
|
|
25
|
-
|
40
|
+
### Setting up a client
|
41
|
+
|
42
|
+
A **client** prepares you to make calls to Napster API.
|
43
|
+
Here is an example code for setting up a client using
|
44
|
+
[implicit method](https://developer.napster.com/api#authentication).
|
45
|
+
|
46
|
+
``` ruby
|
47
|
+
require 'napster'
|
48
|
+
|
49
|
+
options = {
|
50
|
+
api_key: 'API_KEY',
|
51
|
+
api_secret: 'API_SECRET',
|
52
|
+
}
|
53
|
+
|
54
|
+
client = Napster::Client.new(options)
|
55
|
+
```
|
56
|
+
|
57
|
+
You can still set up a client with just an access token. However, you will
|
58
|
+
not be able to refresh the access token and you won't be able to make any
|
59
|
+
metadata calls. Only authenticated member calls will be allowed with this
|
60
|
+
client.
|
61
|
+
|
62
|
+
``` ruby
|
63
|
+
options = { access_token: 'ACCESS_TOKEN' }
|
64
|
+
client = Napster::Client.new(options)
|
65
|
+
```
|
66
|
+
|
67
|
+
### Getting an access token
|
68
|
+
|
69
|
+
#### Password grant
|
70
|
+
|
71
|
+
##### Method 1
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
client_hash = {
|
75
|
+
api_key: 'API_KEY',
|
76
|
+
api_secret: 'API_SECRET',
|
77
|
+
username: 'USERNAME',
|
78
|
+
password: 'PASSWORD'
|
79
|
+
}
|
80
|
+
|
81
|
+
# Just by instantiating with api_key, api_secret, username, and password
|
82
|
+
# you can authenticate by password_grant.
|
83
|
+
client = Napster::Client.new(client_hash)
|
84
|
+
|
85
|
+
client.authentication.access_token # => returns access_token
|
86
|
+
client.authentication.refresh_token
|
87
|
+
client.authentication.expires_in
|
88
|
+
```
|
89
|
+
|
90
|
+
##### Method 2
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
client_hash = {
|
94
|
+
api_key: 'API_KEY',
|
95
|
+
api_secret: 'API_SECRET'
|
96
|
+
}
|
97
|
+
|
98
|
+
client = Napster::Client.new(client_hash)
|
99
|
+
client.username = 'USERNAME'
|
100
|
+
client.password = 'PASSWORD'
|
101
|
+
client.connect
|
102
|
+
|
103
|
+
client.authentication.access_token # => returns access_token
|
104
|
+
client.authentication.refresh_token
|
105
|
+
client.authentication.expires_in
|
106
|
+
```
|
107
|
+
|
108
|
+
#### OAuth 2
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
client_hash = {
|
112
|
+
api_key: 'API_KEY',
|
113
|
+
api_secret: 'API_SECRET',
|
114
|
+
redirect_uri: 'REDIRECT_URI',
|
115
|
+
auth_code: 'AUTH_CODE'
|
116
|
+
}
|
117
|
+
|
118
|
+
client = Napster::Client.new(client_hash)
|
119
|
+
client.connect
|
120
|
+
|
121
|
+
client.authentication.access_token # => returns access_token
|
122
|
+
client.authentication.refresh_token
|
123
|
+
client.authentication.expires_in
|
124
|
+
```
|
125
|
+
|
126
|
+
### Refresh an access token
|
127
|
+
|
128
|
+
Napster API's `access_token` expires in 24 hours after it is issued.
|
129
|
+
You need to use the `refresh_token` to generate a new `access_token` when
|
130
|
+
it is expired.
|
131
|
+
|
132
|
+
*It is not recommended to get a new access_token - refresh_token
|
133
|
+
through authentication after the old access_token expires.*
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
client.refresh # => returns new access_token by refreshing it
|
137
|
+
```
|
138
|
+
|
139
|
+
### Making Requests
|
140
|
+
|
141
|
+
#### Metadata API
|
142
|
+
|
143
|
+
Metadata endpoints do not need the client to be authenticated.
|
144
|
+
First, set up a client with `api_key` and `api_secret`.
|
145
|
+
Then you can call metadata endpoints following this pattern.
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
# takes a form of client.[resources].[method]
|
149
|
+
|
150
|
+
# albums
|
151
|
+
client.albums.new_releases(limit: 10)
|
152
|
+
client.albums.staff_picks(limit: 10)
|
153
|
+
client.albums.top(limit: 10)
|
154
|
+
client.albums.find(artist_id) # => returns an album
|
155
|
+
client.albums.find(artist_name) # => returns an album
|
156
|
+
client.albums.find(artist_id).tracks(limit: 10) # => returns an album
|
157
|
+
client.albums.find(artist_name).tracks(limit: 10) # => returns an album
|
158
|
+
|
159
|
+
# artists
|
160
|
+
client.artists.top(limit: 5)
|
161
|
+
client.artists.find(artist_id) # => returns an artist
|
162
|
+
client.artists.find(artist_name) # => returns an artist
|
163
|
+
client.artists.find(artist_id).albums(offset: 5)
|
164
|
+
client.artists.find(artist_id).new_albums(offset: 5)
|
165
|
+
client.artists.find(artist_id).tracks(limit: 5)
|
166
|
+
client.artists.find(artist_id).top_tracks(limit: 5)
|
167
|
+
|
168
|
+
# favorites
|
169
|
+
client.favorites.members_who_favorited_albums('Alb.5153820')
|
170
|
+
client.favorites.members_who_favorited_artists('Art.954')
|
171
|
+
client.favorites.member_favorites_for('Tra.5156528')
|
172
|
+
|
173
|
+
# members
|
174
|
+
client.members.playlists_for('D877082A5CBC5AC7E040960A390313EF', limit: 2)
|
175
|
+
client.members.favorites_for('D877082A5CBC5AC7E040960A390313EF', limit: 2)
|
176
|
+
client.members.favorite_playlists_for('D877082A5CBC5AC7E040960A390313EF', limit: 2)
|
177
|
+
client.members.chart_for('D877082A5CBC5AC7E040960A390313EF', limit: 2)
|
178
|
+
client.members.find('D877082A5CBC5AC7E040960A390313EF')
|
179
|
+
client.members.find('dduda')
|
180
|
+
client.members.screenname_available?('dduda')
|
181
|
+
client.members.find('dduda').playlists(limit: 5)
|
182
|
+
client.members.find('dduda').favorites(limit: 5)
|
183
|
+
client.members.find('dduda').favorite_playlists(limit: 5)
|
184
|
+
client.members.find('dduda').chart(limit: 5)
|
185
|
+
|
186
|
+
# playlists
|
187
|
+
client.playlists.playlists_of_the_day(limit: 3)
|
188
|
+
client.playlists.featured(limit: 3)
|
189
|
+
client.playlists.find('pp.125821370')
|
190
|
+
client.playlists.find('pp.125821370').tracks(limit: 10)
|
191
|
+
client.playlists.find('pp.125821370').tags
|
192
|
+
|
193
|
+
# tags
|
194
|
+
client.tags.all
|
195
|
+
client.tags.find('tag.156763217')
|
196
|
+
|
197
|
+
# tracks
|
198
|
+
client.tracks.find('Tra.5156528')
|
199
|
+
client.tracks.find_by_name('Marvins Room')
|
200
|
+
```
|
201
|
+
|
202
|
+
#### Authenticated Member API
|
203
|
+
|
204
|
+
Authenticated member endpoints require the client to be authenticated.
|
205
|
+
First, set up a client with `api_key` and `api_secret`.
|
206
|
+
Authenticate the client by going through password grant method or
|
207
|
+
OAuth2 method.
|
208
|
+
Ensure that the client has access_token and refresh_token.
|
209
|
+
Then you can call metadata endpoints following this pattern.
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
# takes a form of client.me.[resources].[method]
|
213
|
+
|
214
|
+
# favorites
|
215
|
+
client.me.favorites.get(limit: 5)
|
216
|
+
client.me.favorites.status(['Art.954', 'Alb.5153820', 'Tra.5156528'])
|
217
|
+
client.me.favorites.add(['Art.954', 'Alb.5153820', 'Tra.5156528'])
|
218
|
+
client.me.favorites.remove('Art.954')
|
219
|
+
|
220
|
+
# followers
|
221
|
+
client.me.followers.members(limit: 5)
|
222
|
+
client.me.followers.by?(guids)
|
223
|
+
|
224
|
+
# following
|
225
|
+
client.me.following.members(limit: 5)
|
226
|
+
client.me.following.by?(guids)
|
227
|
+
client.me.following.follow(guids)
|
228
|
+
client.me.following.unfollow(guids)
|
229
|
+
|
230
|
+
# library
|
231
|
+
client.me.library.artists(limit: 10)
|
232
|
+
client.me.library.artist_albums('Art.954', limit: 10)
|
233
|
+
client.me.library.artist_tracks('Art.954', limit: 10)
|
234
|
+
client.me.library.albums(limit: 10)
|
235
|
+
client.me.library.album_tracks('Alb.5153820', limit: 10)
|
236
|
+
client.me.library.tracks(limit: 10)
|
237
|
+
client.me.library.add_track(['Tra.5156528'])
|
238
|
+
client.me.library.remove_track('Tra.5156528')
|
239
|
+
client.me.library.last_updated_date
|
240
|
+
|
241
|
+
# listening history
|
242
|
+
client.me.listening_history(limit: 10)
|
243
|
+
|
244
|
+
# playlists
|
245
|
+
client.me.playlists.all(limit: 10)
|
246
|
+
client.me.playlists.create({ 'name' => 'hiphop playlist' })
|
247
|
+
client.me.playlists.find('mp.123123')
|
248
|
+
client.me.playlists.update('mp.123123', { 'name' => 'hiphop playlist 2' })
|
249
|
+
client.me.playlists.delete('mp.123123')
|
250
|
+
client.me.playlists.set_private('mp.123123', 'public')
|
251
|
+
client.me.playlists.set_private('mp.123123', 'private')
|
252
|
+
client.me.playlists.add_tracks('mp.123123', ['Tra.5156528'])
|
253
|
+
client.me.playlists.recommended_tracks('mp.123123')
|
254
|
+
client.me.playlists.uploaded_images(id: 'mp.123123', size: 500) # id and size in px
|
255
|
+
client.me.playlists.sourced_by('my_own_playlists',
|
256
|
+
{ artists: ['art.123', 'art.234'], tags: ['tag.123', 'tag.234'], guid: 'xyz', sort: 'alpha_asc', include_private: true, limit: 10, offset: 5})
|
257
|
+
client.me.playlists.find('mp.123123').tracks(limit: 10)
|
258
|
+
client.me.playlists.find('mp.123123').tags
|
259
|
+
client.me.playlists.find('mp.123123').uploaded_images(500) # size in px
|
260
|
+
|
261
|
+
# profile
|
262
|
+
client.me.profile.get
|
263
|
+
client.me.profile.update({ 'me' => { 'bio' => Faker::Lorem.word } })
|
264
|
+
|
265
|
+
# tags
|
266
|
+
client.me.tags.contents('favorite', '', {})
|
267
|
+
```
|
268
|
+
|
269
|
+
#### Query Parameters
|
270
|
+
|
271
|
+
```ruby
|
272
|
+
client.artists.top(limit: 5, offset: 5)
|
273
|
+
```
|
274
|
+
|
275
|
+
#### Request body for PUT / POST
|
276
|
+
|
277
|
+
```ruby
|
278
|
+
request_hash = {
|
279
|
+
body: {
|
280
|
+
name: 'name of the playlist',
|
281
|
+
tags: ['tag.1', 'tag.2'],
|
282
|
+
privacy: 'public',
|
283
|
+
tracks: ['tra.1', 'tra.2']
|
284
|
+
}
|
285
|
+
}
|
286
|
+
client.me.create_playlist(request_hash)
|
287
|
+
```
|
288
|
+
|
289
|
+
#### Error Handling
|
290
|
+
|
291
|
+
Napster gem provides `ResponseError` which wraps response errors from Napster
|
292
|
+
API. You can inspect error attributes as shown below.
|
293
|
+
|
294
|
+
```ruby
|
295
|
+
begin
|
296
|
+
client.playlists.find('pp.125821370').tracks({}) # problematic request
|
297
|
+
rescue Exception => error
|
298
|
+
puts error.http_status # => 400
|
299
|
+
puts error.response_body
|
300
|
+
# => {"code":"BadRequestError","message":"limit query parameter is required"}
|
301
|
+
puts error.faraday_response.inspect
|
302
|
+
# => #<Faraday::Response:0x007fe9bc957150 @on_complete_callbacks=[], ...
|
303
|
+
end
|
304
|
+
```
|
305
|
+
|
306
|
+
<!--
|
307
|
+
### Versioning
|
308
|
+
|
309
|
+
The Napster gem supports Napster API version 2.x and above only.
|
310
|
+
When the client does not specify the version, it'll use the latest
|
311
|
+
Napster API version.
|
312
|
+
|
313
|
+
#### Versioned client
|
314
|
+
|
315
|
+
You can set client to always use a specific version of Napster API.
|
316
|
+
|
317
|
+
```ruby
|
318
|
+
client.version = 'v2.1'
|
319
|
+
client.artists.top # returns top artists using v2.1
|
320
|
+
```
|
321
|
+
|
322
|
+
#### Making one-off versioned request
|
323
|
+
|
324
|
+
Even though the client already has a version set, you can still make
|
325
|
+
one-off calls to a different version of Napster API.
|
326
|
+
|
327
|
+
```ruby
|
328
|
+
client.version = 'v2.1'
|
329
|
+
client.v2_2.artists.top # returns top artists using v2.2
|
330
|
+
client.artists.top # returns top artists using v2.1
|
331
|
+
```
|
332
|
+
-->
|
26
333
|
|
27
334
|
## Development
|
28
335
|
|
29
|
-
|
336
|
+
### Running tests
|
30
337
|
|
31
|
-
|
338
|
+
Napster gem uses RSpec and FactoryGirl.
|
32
339
|
|
33
|
-
|
340
|
+
1. Get the API key and API secret from
|
341
|
+
[Napster Developers site](https://developer.napster.com/).
|
342
|
+
|
343
|
+
2. Create a file called `config.yml` in `spec` directory.
|
344
|
+
|
345
|
+
3. Add the following with the correct API key and API secret
|
34
346
|
|
35
|
-
|
347
|
+
``` yml
|
348
|
+
config_variables:
|
349
|
+
API_KEY: 'API_KEY'
|
350
|
+
API_SECRET: 'API_SECRET'
|
351
|
+
USERNAME: 'USERNAME'
|
352
|
+
PASSWORD: 'PASSWORD'
|
353
|
+
REDIRECT_URI: 'REDIRECT_URI'
|
354
|
+
```
|
355
|
+
|
356
|
+
4. `$ bundle install`
|
357
|
+
|
358
|
+
5. `$ rspec`
|
359
|
+
|
360
|
+
|
361
|
+
## Contributing
|
36
362
|
|
363
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/napster/napster-ruby.
|
37
364
|
|
38
365
|
## License
|
39
366
|
|
40
367
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
41
368
|
|
369
|
+
Napster and Napster logo are registered and unregistered trademarks of Rhapsody International in the United States and/or other countries. All company, product and service names used in this website are for identification purposes only. All product names, logos, and brands are property of their respective owners.
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'napster'
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +10,5 @@ require "napster"
|
|
10
10
|
# require "pry"
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
-
require
|
13
|
+
require 'irb'
|
14
14
|
IRB.start
|