officialfm 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +0 -5
- data/Gemfile +6 -0
- data/Gemfile.lock +41 -0
- data/README.md +174 -42
- data/Rakefile +0 -1
- data/lib/officialfm/client.rb +59 -55
- data/lib/officialfm/playlists.rb +35 -131
- data/lib/officialfm/projects.rb +65 -0
- data/lib/officialfm/tracks.rb +12 -194
- data/lib/officialfm/version.rb +1 -1
- data/lib/officialfm.rb +2 -8
- data/officialfm.gemspec +10 -16
- data/test/client_test.rb +97 -0
- data/test/helper.rb +10 -36
- data/test/tracks_test.rb +17 -38
- metadata +88 -216
- data/.document +0 -5
- data/LICENSE +0 -24
- data/changelog.md +0 -25
- data/lib/faraday/request/officialfm_oauth.rb +0 -23
- data/lib/officialfm/authentication.rb +0 -31
- data/lib/officialfm/users.rb +0 -251
- data/test/fixtures/charts.json +0 -1552
- data/test/fixtures/latest.json +0 -1552
- data/test/fixtures/playlist.json +0 -20
- data/test/fixtures/playlist_votes.json +0 -21
- data/test/fixtures/playlists.json +0 -122
- data/test/fixtures/track.json +0 -33
- data/test/fixtures/track_votes.json +0 -306
- data/test/fixtures/tracks.json +0 -157
- data/test/fixtures/user.json +0 -22
- data/test/fixtures/user_contacts.json +0 -40
- data/test/fixtures/user_playlists.json +0 -38
- data/test/fixtures/user_subscribers.json +0 -40
- data/test/fixtures/user_subscriptions.json +0 -40
- data/test/fixtures/user_tracks.json +0 -66
- data/test/fixtures/voted_playlists.json +0 -50
- data/test/fixtures/voted_tracks.json +0 -96
- data/test/playlists_test.rb +0 -32
- data/test/users_test.rb +0 -87
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
officialfm (0.2.0)
|
5
|
+
faraday (~> 0.8.1)
|
6
|
+
faraday_middleware (~> 0.8.8)
|
7
|
+
hashie (~> 1.2)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
faraday (0.8.1)
|
13
|
+
multipart-post (~> 1.1)
|
14
|
+
faraday_middleware (0.8.8)
|
15
|
+
faraday (>= 0.7.4, < 0.9)
|
16
|
+
hashie (1.2.0)
|
17
|
+
jnunemaker-matchy (0.4.0)
|
18
|
+
multi_json (1.3.6)
|
19
|
+
multipart-post (1.1.5)
|
20
|
+
rake (0.9.2.2)
|
21
|
+
shoulda (2.11.3)
|
22
|
+
simplecov (0.6.0)
|
23
|
+
multi_json (~> 1.0)
|
24
|
+
simplecov-html (~> 0.5.3)
|
25
|
+
simplecov-gem-adapter (1.0.1)
|
26
|
+
simplecov
|
27
|
+
simplecov-html (0.5.3)
|
28
|
+
test-unit (2.5.1)
|
29
|
+
|
30
|
+
PLATFORMS
|
31
|
+
ruby
|
32
|
+
|
33
|
+
DEPENDENCIES
|
34
|
+
bundler (~> 1.0)
|
35
|
+
jnunemaker-matchy (~> 0.4)
|
36
|
+
officialfm!
|
37
|
+
rake (~> 0.8)
|
38
|
+
shoulda (~> 2.11)
|
39
|
+
simplecov (~> 0.6.0)
|
40
|
+
simplecov-gem-adapter (~> 1.0.1)
|
41
|
+
test-unit (~> 2.1)
|
data/README.md
CHANGED
@@ -1,69 +1,201 @@
|
|
1
1
|
# official.fm
|
2
2
|
|
3
|
-
Ruby wrapper for the [official.fm
|
3
|
+
Ruby wrapper for the [official.fm v2 API](http://official.fm/developers).
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
7
|
-
|
7
|
+
gem install officialfm
|
8
|
+
|
9
|
+
Alternatively put this in you `Gemfile`, then run `bundle install`:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'officialfm'
|
13
|
+
```
|
8
14
|
|
9
15
|
## Get your API key
|
10
16
|
|
11
|
-
|
17
|
+
Coming soon.
|
12
18
|
|
13
|
-
|
19
|
+
You can also access the API without an API key, but with a lower rate limit.
|
14
20
|
|
15
|
-
|
21
|
+
## Client instantiation and configuration
|
16
22
|
|
17
|
-
|
18
|
-
require 'officialfm'
|
23
|
+
Include the relevant files
|
19
24
|
|
20
|
-
|
21
|
-
|
22
|
-
|
25
|
+
```ruby
|
26
|
+
require 'officialfm'
|
27
|
+
```
|
23
28
|
|
24
|
-
|
29
|
+
Instantiate a client
|
25
30
|
|
26
|
-
|
27
|
-
|
31
|
+
```ruby
|
32
|
+
officialfm = OfficialFM::Client.new
|
33
|
+
```
|
28
34
|
|
29
|
-
|
30
|
-
puts "#{track.name} by #{track.artist_string}"
|
31
|
-
end
|
32
|
-
|
33
|
-
For a complete example of web-app using Sinatra in conjunction with
|
34
|
-
this gem, see [ofmtweet](https://github.com/nddrylliog/ofmtweet).
|
35
|
+
With an API key:
|
35
36
|
|
36
|
-
|
37
|
+
```ruby
|
38
|
+
officialfm = OfficialFM::Client.new(api_key: 'your_api_key')
|
39
|
+
```
|
37
40
|
|
38
|
-
|
41
|
+
You can also set a default configuration for all clients to use
|
39
42
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
+
```ruby
|
44
|
+
OfficialFM.configure do |c|
|
45
|
+
c.api_key = YOUR_API_KEY
|
46
|
+
end
|
47
|
+
```
|
43
48
|
|
44
|
-
|
45
|
-
the gem allows you to access it like this:
|
49
|
+
## Response format
|
46
50
|
|
47
|
-
|
51
|
+
All methods return a
|
52
|
+
[Hashie:Mash](http://rdoc.info/github/intridea/hashie/Hashie/Mash). That means
|
53
|
+
you can access the response fields via method-like accessors. For example:
|
48
54
|
|
49
|
-
|
55
|
+
```ruby
|
56
|
+
search_results = officialfm.tracks('Wiz Khalifa')
|
57
|
+
track = search_results[3].track
|
58
|
+
puts "#{track.title} by #{track.artist}"
|
59
|
+
```
|
50
60
|
|
51
|
-
|
52
|
-
* Make your feature addition or bug fix.
|
53
|
-
* Add tests for it. This is important so I don't break it in a
|
54
|
-
future version unintentionally.
|
55
|
-
* Commit, do not mess with rakefile, version, or history.
|
56
|
-
(if you want to have your own version, that is fine but
|
57
|
-
bump version in a commit by itself I can ignore when I pull)
|
58
|
-
* Send me a pull request. Bonus points for topic branches.
|
61
|
+
## API response enhancements
|
59
62
|
|
60
|
-
|
63
|
+
The API wraps responses in a root element, e.g.:
|
64
|
+
|
65
|
+
```json
|
66
|
+
{
|
67
|
+
"track": {
|
68
|
+
"title": "Some track"
|
69
|
+
...
|
70
|
+
}
|
71
|
+
}
|
72
|
+
```
|
73
|
+
|
74
|
+
The responses given by methods in the gem don't have a root and expose the
|
75
|
+
resource's properites directly instead (e.g. `officialfm.track('xxxx').title`).
|
76
|
+
|
77
|
+
Search results are also unwrapped. For example, the raw response of a track
|
78
|
+
search looks like:
|
79
|
+
|
80
|
+
```json
|
81
|
+
{
|
82
|
+
"page": 1,
|
83
|
+
"total_entries": 2,
|
84
|
+
"total_pages": 1,
|
85
|
+
"tracks" : [
|
86
|
+
{
|
87
|
+
"track": {
|
88
|
+
// track properties
|
89
|
+
}
|
90
|
+
},
|
91
|
+
{
|
92
|
+
"track": {
|
93
|
+
// track properites
|
94
|
+
}
|
95
|
+
}
|
96
|
+
]
|
97
|
+
}
|
98
|
+
```
|
99
|
+
|
100
|
+
The gem removes the roots of the search result items, so you can access an item
|
101
|
+
directly through array access.
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
track = officialfm.tracks('foo').tracks[0]
|
105
|
+
puts track.duration
|
106
|
+
```
|
107
|
+
|
108
|
+
|
109
|
+
## Methods
|
110
|
+
|
111
|
+
### Tracks
|
112
|
+
Search for a track:
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
officialfm.tracks('Nightcall')
|
116
|
+
```
|
117
|
+
|
118
|
+
Search results being paged, you can request a specific page with the page parameter.
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
officialfm.tracks('Kids', page: 2)
|
122
|
+
```
|
123
|
+
|
124
|
+
Get info about a specific track:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
officialfm.track('1nnQ')
|
128
|
+
```
|
129
|
+
|
130
|
+
### Playlists
|
131
|
+
|
132
|
+
Search for a playlist (again you can pass an optional `page` parameter to get a
|
133
|
+
specific results page):
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
officialfm.playlists('AWOLNATION')
|
137
|
+
```
|
61
138
|
|
62
|
-
|
139
|
+
Get info about a specific playlist:
|
63
140
|
|
64
|
-
|
141
|
+
```ruby
|
142
|
+
officialfm.playlist('CbqY')
|
143
|
+
```
|
144
|
+
|
145
|
+
Retrieve the tracks in a playlist:
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
playlists = officialfm.playlists('AWOLNATION')
|
149
|
+
|
150
|
+
# The tracks for the 3 playlist in the search results
|
151
|
+
tracks = playlists[2].tracks
|
152
|
+
```
|
153
|
+
|
154
|
+
Note that the `tracks` method of a playlist object makes an extra request. If
|
155
|
+
you know the playlist ID in advance, you can retrieve the tracks in just one
|
156
|
+
request.
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
officialfm.playlist_tracks('CbqY')
|
160
|
+
```
|
161
|
+
|
162
|
+
### Projects
|
163
|
+
|
164
|
+
Search for a project (a project can be an artist or a collaboration between several artists)
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
officialfm.projects('Mac Miller x Pharrell')
|
168
|
+
```
|
169
|
+
|
170
|
+
Similarly to playlists, you can get information about a specific project with
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
officialfm.project('edB6')
|
174
|
+
```
|
175
|
+
|
176
|
+
Get a project's tracks or playlists when you know the project ID in advance.
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
tracks = officialfm.project_tracks('edB6')
|
180
|
+
playlists = officialfm.project_playlists('edB6')
|
181
|
+
puts artist.tracks
|
182
|
+
puts artist.playlists
|
183
|
+
```
|
184
|
+
|
185
|
+
Of course you can get the playlists and tracks in a project even if you don't know its ID:
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
projects = officialfm.projects('Mac Miller')
|
189
|
+
|
190
|
+
puts projects[0].name # => 'Mac Miller'
|
191
|
+
puts projects[2].name # => 'Mac Miller x Pharrell'
|
192
|
+
|
193
|
+
tracks = projects[2].tracks
|
194
|
+
|
195
|
+
```
|
196
|
+
|
197
|
+
|
198
|
+
## Copyright
|
65
199
|
|
66
|
-
|
200
|
+
Copyright (c) 2012 official.fm
|
67
201
|
|
68
|
-
A huge load of thanks to pengwynn for releasing it open-source! It was wonderful
|
69
|
-
to work from his extra-clean codebase.
|
data/Rakefile
CHANGED
data/lib/officialfm/client.rb
CHANGED
@@ -1,83 +1,50 @@
|
|
1
|
-
require 'forwardable'
|
2
|
-
require 'faraday/request/officialfm_oauth'
|
3
|
-
require 'officialfm/authentication'
|
4
1
|
require 'officialfm/version'
|
5
2
|
|
6
3
|
module OfficialFM
|
7
4
|
class Client
|
8
|
-
extend Forwardable
|
9
5
|
|
10
|
-
include Users
|
11
6
|
include Tracks
|
12
7
|
include Playlists
|
13
|
-
include
|
14
|
-
|
15
|
-
attr_reader :api_key, :api_secret
|
8
|
+
include Projects
|
16
9
|
|
17
|
-
|
10
|
+
attr_reader :api_key
|
18
11
|
|
19
12
|
def initialize(options={})
|
20
13
|
@api_key = options[:api_key] || OfficialFM.api_key
|
21
|
-
|
22
|
-
@access_token = options[:access_token]
|
23
|
-
@access_secret = options[:access_secret]
|
24
|
-
# Note: Although the default of the API is to return XML, I think
|
25
|
-
# json is more appropriate in the Ruby world
|
26
|
-
|
27
|
-
@format = options[:format] || :json
|
28
|
-
connection unless @access_token
|
14
|
+
connection(options)
|
29
15
|
end
|
30
16
|
|
31
|
-
# GET request arguments for simple API calls
|
32
|
-
def simple_params (options = nil)
|
33
|
-
params = {
|
34
|
-
:key => @api_key,
|
35
|
-
:format => @format,
|
36
|
-
}
|
37
|
-
if options
|
38
|
-
options.each { |key, value|
|
39
|
-
case key
|
40
|
-
when 'limit'
|
41
|
-
params['api_max_responses'] = value
|
42
|
-
when 'embed'
|
43
|
-
params['api_embed_codes'] = value
|
44
|
-
else
|
45
|
-
params[key] = value
|
46
|
-
end
|
47
|
-
}
|
48
|
-
end
|
49
|
-
params
|
50
|
-
end
|
51
17
|
|
52
|
-
#
|
18
|
+
# Faraday::Connection used for all HTTP requests
|
53
19
|
#
|
54
20
|
# @return [Faraday::Connection]
|
55
|
-
def connection
|
56
|
-
|
57
|
-
|
58
|
-
options = {
|
59
|
-
:url => api_url,
|
21
|
+
def connection(options={})
|
22
|
+
config = {
|
23
|
+
:url => api_url,
|
60
24
|
:headers => default_headers
|
61
|
-
}
|
62
|
-
|
63
|
-
@connection ||= Faraday.new(
|
64
|
-
builder.use Faraday::Request::OfficialFMOAuth, authentication if authenticated?
|
65
|
-
builder.use Faraday::Request::Multipart
|
66
|
-
builder.use Faraday::Request::UrlEncoded
|
67
|
-
|
68
|
-
builder.use Faraday::Response::Mashify
|
69
|
-
builder.use Faraday::Response::ParseJson
|
25
|
+
}.merge(options)
|
26
|
+
|
27
|
+
@connection ||= Faraday.new(config) do |builder|
|
70
28
|
builder.adapter Faraday.default_adapter
|
29
|
+
|
30
|
+
builder.request :url_encoded
|
31
|
+
|
32
|
+
builder.response :mashify
|
33
|
+
builder.response :json
|
71
34
|
end
|
72
35
|
|
73
36
|
end
|
74
|
-
|
37
|
+
|
75
38
|
# @private
|
76
39
|
def default_headers
|
77
40
|
headers = {
|
78
|
-
|
79
|
-
:
|
41
|
+
'X-API-Version' => '2.0',
|
42
|
+
:accept => 'application/json',
|
43
|
+
:user_agent => "officialfm v2 ruby gem version #{OfficialFM::VERSION}"
|
80
44
|
}
|
45
|
+
headers['X-API-KEY'] = @api_key if @api_key
|
46
|
+
|
47
|
+
headers
|
81
48
|
end
|
82
49
|
|
83
50
|
# Provides the URL for accessing the API
|
@@ -86,5 +53,42 @@ module OfficialFM
|
|
86
53
|
def api_url
|
87
54
|
"http://api.official.fm"
|
88
55
|
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
# Returns the url for a resource.
|
60
|
+
#
|
61
|
+
# - id: resource id or URL
|
62
|
+
# - options: extra params. Supports 'parent' and 'child' options.
|
63
|
+
#
|
64
|
+
# resource_url('http://api.official.fm/playlists/2BHH', :child => :tracks)
|
65
|
+
# # => http://api.official.fm/playlists/2BHH/tracks
|
66
|
+
#
|
67
|
+
# resource_url('2BHH', { :parent => 'playlists', :child => 'tracks'})
|
68
|
+
# # => /playlists/2BHH/tracks
|
69
|
+
#
|
70
|
+
# Note: if you supply a full resource URL, the parent option is ignored.
|
71
|
+
#
|
72
|
+
def resource_url(id, options={})
|
73
|
+
raise "Resource id cannot be nil" unless id
|
74
|
+
|
75
|
+
parent = options.fetch(:parent, nil)
|
76
|
+
child = options.fetch(:child, nil)
|
77
|
+
|
78
|
+
if id.start_with? 'http'
|
79
|
+
return [id, child].join '/'
|
80
|
+
end
|
81
|
+
|
82
|
+
url = [parent, id, child].join('/').chomp('/')
|
83
|
+
url = "/#{url}" unless url.start_with? '/'
|
84
|
+
|
85
|
+
url
|
86
|
+
end
|
87
|
+
|
88
|
+
def extend_response(response, mixin_module)
|
89
|
+
response.obj = self
|
90
|
+
response.extend(mixin_module)
|
91
|
+
end
|
92
|
+
|
89
93
|
end
|
90
94
|
end
|
data/lib/officialfm/playlists.rb
CHANGED
@@ -1,145 +1,49 @@
|
|
1
|
-
require 'cgi'
|
2
|
-
|
3
1
|
module OfficialFM
|
4
2
|
module Playlists
|
5
|
-
|
6
|
-
# Search for
|
7
|
-
#
|
8
|
-
# @param [String] search_param: a search parameter (eg. name of the playlist)
|
9
|
-
# @param [Integer] limit (50) limit per page (optional)
|
10
|
-
# @return [Hashie::Mash] Playlist list
|
3
|
+
|
4
|
+
# Search for a playlist
|
11
5
|
def playlists(search_param, options={})
|
12
|
-
response = connection.get
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
# @param [String] track_id: id
|
22
|
-
# @param [Bool] embed (false) should embed codes be included in the response
|
23
|
-
# @return [Hashie::Mash] Playlist
|
24
|
-
def playlist(playlist_id, options={})
|
25
|
-
response = connection.get do |req|
|
26
|
-
req.url "/playlist/#{playlist_id}", simple_params(options)
|
27
|
-
end
|
28
|
-
improve(response.body[0])
|
29
|
-
end
|
30
|
-
|
31
|
-
# Retrieve users that have voted for this playlist
|
32
|
-
#
|
33
|
-
# @param [String] playlist_id: id
|
34
|
-
# @param [Integer] limit (50) limit per page
|
35
|
-
# @return [Hashie::Mash] User list
|
36
|
-
def playlist_votes(playlist_id, options={})
|
37
|
-
response = connection.get do |req|
|
38
|
-
req.url "/playlist/#{playlist_id}/votes", simple_params(options)
|
6
|
+
response = connection.get '/playlists/search', options.merge(:q => search_param)
|
7
|
+
|
8
|
+
response.body.playlists.map! do |p|
|
9
|
+
# remove the unnecessary root
|
10
|
+
actual_playlist = p.playlist
|
11
|
+
|
12
|
+
extend_response(actual_playlist, PlaylistMethods)
|
13
|
+
|
14
|
+
actual_playlist
|
39
15
|
end
|
16
|
+
|
40
17
|
response.body
|
41
18
|
end
|
42
|
-
|
43
|
-
def improve(playlist)
|
44
|
-
# the length field is already used. Note: running_time is in seconds
|
45
|
-
playlist.running_time = playlist["length"]
|
46
|
-
playlist
|
47
|
-
end
|
48
|
-
|
49
|
-
####################################################################
|
50
|
-
######################### Advanced API methods #####################
|
51
|
-
####################################################################
|
52
19
|
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
# @param [String] private (optional)
|
60
|
-
# @return [Hashie::Mash] Playlist
|
61
|
-
def update_playlist! (playlist_id, data = {})
|
62
|
-
check_auth :update_playlist
|
63
|
-
|
64
|
-
response = connection.put do |req|
|
65
|
-
req.url "/playlist/update/#{playlist_id}", data
|
66
|
-
req.body = { :format => @format }
|
67
|
-
end
|
68
|
-
response
|
69
|
-
end
|
70
|
-
|
71
|
-
# Upload a picture for a given playlist
|
72
|
-
#
|
73
|
-
# @param [String] playlist_id: id
|
74
|
-
# @param [String] path: path to a picture
|
75
|
-
# @param [String] mime: the mime-type of the picture (e.g. image/jpeg, image/png, etc.)
|
76
|
-
# @return [Hashie::Mash] Success or error message
|
77
|
-
def playlist_picture! (playlist_id, path, mime)
|
78
|
-
check_auth :playlist_picture
|
79
|
-
|
80
|
-
response = connection.post do |req|
|
81
|
-
req.url "/playlist/picture/#{playlist_id}"
|
82
|
-
req.body = { :file => Faraday::UploadIO.new(path, mime), :format => @format }
|
83
|
-
end
|
84
|
-
response
|
85
|
-
end
|
86
|
-
|
87
|
-
# Remove a playlist
|
88
|
-
#
|
89
|
-
# @param [String] playlist_id: id
|
90
|
-
# @return [Hashie::Mash] Success or error message
|
91
|
-
def playlist_remove! (playlist_id)
|
92
|
-
check_auth :playlist_remove
|
93
|
-
|
94
|
-
response = connection.delete do |req|
|
95
|
-
req.url "/playlist/remove/#{playlist_id}"
|
96
|
-
req.body = { :format => @format }
|
97
|
-
end
|
98
|
-
response
|
99
|
-
end
|
100
|
-
|
101
|
-
# Create a playlist
|
102
|
-
#
|
103
|
-
# @param [String] name: playlist name
|
104
|
-
# @param [String] track_id: first track id of the new playlist
|
105
|
-
# @return [Hashie::Mash] Playlist object
|
106
|
-
def playlist_create! (name, track_id)
|
107
|
-
check_auth :playlist_create
|
108
|
-
|
109
|
-
response = connection.post do |req|
|
110
|
-
req.url "/playlist/create"
|
111
|
-
req.body = { :format => @format, :name => name, :track_id => track_id }
|
112
|
-
end
|
113
|
-
response
|
20
|
+
# Retrieve information about a specific playlist
|
21
|
+
def playlist(id, options={})
|
22
|
+
url = resource_url(id, parent: 'playlists')
|
23
|
+
|
24
|
+
response = connection.get(url, options).body.playlist
|
25
|
+
extend_response(response, PlaylistMethods)
|
114
26
|
end
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
req.url "/playlist/vote/#{playlist_id}"
|
125
|
-
req.body = { :format => @format }
|
27
|
+
|
28
|
+
def playlist_tracks(id, options={})
|
29
|
+
url = resource_url(id, { parent: 'playlists', child: 'tracks' })
|
30
|
+
|
31
|
+
response = connection.get url, options
|
32
|
+
|
33
|
+
tracks = response.body.tracks.map do |t|
|
34
|
+
# remove the unnecessary root
|
35
|
+
t.track
|
126
36
|
end
|
127
|
-
|
37
|
+
|
38
|
+
tracks
|
128
39
|
end
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
def playlist_unvote! (playlist_id)
|
135
|
-
check_auth :playlist_unvote
|
136
|
-
|
137
|
-
response = connection.post do |req|
|
138
|
-
req.url "/playlist/unvote/#{playlist_id}"
|
139
|
-
req.body = { :format => @format }
|
40
|
+
|
41
|
+
module PlaylistMethods
|
42
|
+
|
43
|
+
def tracks
|
44
|
+
obj.playlist_tracks(self.src)
|
140
45
|
end
|
141
|
-
response
|
142
46
|
end
|
143
|
-
|
47
|
+
|
144
48
|
end
|
145
49
|
end
|