File Coverage

blib/lib/WebService/Spotify.pm
Criterion Covered Total %
statement 82 245 33.4
branch 14 148 9.4
condition n/a
subroutine 36 54 66.6
pod n/a
total 132 447 29.5


line stmt bran cond sub pod time code
1             package WebService::Spotify;
2 1     1   128281 use Moo;
  1         31219  
  1         10  
3 1     1   3156 use Method::Signatures;
  1         112350  
  1         13  
4 1     1   1894 use LWP::UserAgent;
  1         185902  
  1         34  
5 1     1   760 use URI::QueryParam;
  1         650  
  1         26  
6 1     1   1011 use JSON;
  1         858085  
  1         11  
7 1     1   265 use Data::Dumper;
  1         4  
  1         299  
8              
9             our $VERSION = '1.002';
10              
11             has 'prefix' => ( is => 'rw', default => 'https://api.spotify.com/v1/' );
12             has 'auth' => ( is => 'rw' );
13             has 'trace' => ( is => 'rw', default => 0 );
14              
15             has 'user_agent' => (
16             is => 'rw',
17             default => sub {
18             my $ua = LWP::UserAgent->new;
19             $ua->agent("WebService::Spotify/$VERSION");
20             return $ua;
21             }
22             );
23              
24 1 50   1   550377 method get ($method, %args) {
  1     1   3  
  1         10  
  1         3  
  1         7  
25 1         10 my $uri = $self->_uri( $method, %args );
26 1         7 my $headers = $self->_auth_headers;
27 1         14 my $response = $self->user_agent->get( $uri->as_string, %$headers );
28            
29 1         7080 $self->_log("GET", $uri->as_string);
30 1         6 $self->_log("RESP", $response->content);
31              
32 1 50       4 return $response->content ? from_json($response->content) : undef;
33             }
34              
35 1 0   1   3355 method post ($method, $payload, %args) {
  0 0   0   0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
36 0         0 my $uri = $self->_uri( $method, %args );
37 0         0 my $headers = $self->_auth_headers;
38 0         0 $headers->{'Content-Type'} = 'application/json';
39 0         0 my $response = $self->user_agent->post( $uri->as_string, %$headers, Content => to_json($payload) );
40            
41 0         0 $self->_log("POST", $uri->as_string);
42 0         0 $self->_log("HEAD", Dumper $headers);
43 0         0 $self->_log("DATA", Dumper $payload);
44 0         0 $self->_log("RESP", $response->content);
45              
46 0 0       0 return $response->content ? from_json($response->content) : undef;
47             }
48              
49 1 0   1   1830 method next ($result) {
  0 0   0   0  
  0         0  
  0         0  
  0         0  
50 0 0       0 return $self->get($result->{next}) if $result->{next};
51             }
52              
53 1 0   1   1904 method previous ($result) {
  0 0   0   0  
  0         0  
  0         0  
  0         0  
54 0 0       0 return $self->get($result->{previous}) if $result->{previous};
55             }
56              
57 1 0   1   1686 method track ($track) {
  0 0   0   0  
  0         0  
  0         0  
  0         0  
58 0         0 my $track_id = $self->_get_id('track', $track);
59 0         0 return $self->get("tracks/$track_id");
60             }
61              
62 1 0   1   1579 method tracks ($tracks) {
  0 0   0   0  
  0         0  
  0         0  
  0         0  
63 0         0 my @track_ids = map { $self->_get_id('track', $_) } @$tracks;
  0         0  
64 0         0 return $self->get('tracks/?ids=' . join(',', @track_ids));
65             }
66              
67 1 50   1   2200 method artist ($artist) {
  1 50   1   1092  
  1         8  
  1         3  
  1         6  
68 1         7 my $artist_id = $self->_get_id('artist', $artist);
69 1         10 return $self->get("artists/$artist_id");
70             }
71              
72 1 0   1   1732 method artists ($artists) {
  0 0   0   0  
  0         0  
  0         0  
  0         0  
73 0         0 my @artist_ids = map { $self->_get_id('artist', $_) } @$artists;
  0         0  
74 0         0 return $self->get('artists/?ids=' . join(',', @artist_ids));
75             }
76              
77 1 0   1   9221 method artist_albums ($artist, :$album_type, :$country, :$limit = 20, :$offset = 0) {
  0 0   0   0  
  0 0       0  
  0 0       0  
  0 0       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
78 0         0 my $artist_id = $self->_get_id('artist', $artist);
79 0         0 my %options;
80 0 0       0 $options{album_type} = $album_type if $album_type;
81 0 0       0 $options{country} = $country if $country;
82 0         0 return $self->get("artists/$artist_id/albums", %options, limit => $limit, offset => $offset);
83             }
84              
85 1 0   1   6420 method artist_top_tracks ($artist, :$country = 'US') {
  0 0   0   0  
  0 0       0  
  0 0       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
86 0         0 my $artist_id = $self->_get_id('artist', $artist);
87 0         0 return $self->get("artists/$artist_id/top-tracks", country => $country);
88             }
89              
90 1 0   1   1978 method album ($album) {
  0 0   0   0  
  0         0  
  0         0  
  0         0  
91 0         0 my $album_id = $self->_get_id('album', $album);
92 0         0 return $self->get("albums/$album_id");
93             }
94              
95 1 0   1   1930 method album_tracks ($album) {
  0 0   0   0  
  0         0  
  0         0  
  0         0  
96 0         0 my $album_id = $self->_get_id('album', $album);
97 0         0 return $self->get("albums/$album_id/tracks");
98             }
99              
100 1 0   1   1929 method albums ($albums) {
  0 0   0   0  
  0         0  
  0         0  
  0         0  
101 0         0 my @album_ids = map { $self->_get_id('album', $_) } @$albums;
  0         0  
102 0         0 return $self->get('albums/?ids=' . join(',', @album_ids));
103             }
104              
105 1 0   1   9536 method search ($q, :$limit = 10, :$offset = 0, :$type = 'track') {
  0 0   0   0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
106 0         0 return $self->get('search', q => $q, limit => $limit, offset => $offset, type => $type);
107             }
108              
109 1 0   1   1874 method user ($user_id) {
  0 0   0   0  
  0         0  
  0         0  
  0         0  
110 0         0 return $self->get("users/$user_id");
111             }
112              
113 1 0   1   1862 method user_playlists ($user_id) {
  0 0   0   0  
  0         0  
  0         0  
  0         0  
114 0         0 return $self->get("users/$user_id/playlists");
115             }
116              
117 1 0   1   4057 method user_playlist ($user_id, :$playlist_id, :$fields) {
  0 0   0   0  
  0 0       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
118 0 0       0 my $method = $playlist_id ? "playlists/$playlist_id" : "starred";
119 0         0 return $self->get("users/$user_id/$method", $fields => $fields);
120             }
121              
122 1 0   1   5394 method user_playlist_create ($user_id, $name, :$public = 1) {
  0 0   0   0  
  0 0       0  
  0 0       0  
  0 0       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
123 0         0 my $data = { 'name' => $name, 'public' => $public };
124 0         0 return $self->post("users/$user_id/playlists", $data);
125             }
126              
127 1 0   1   3597 method user_playlist_add_tracks ($user_id, $playlist_id, $tracks, :$position) {
  0 0   0   0  
  0 0       0  
  0 0       0  
  0 0       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
128 0         0 my %options;
129 0 0       0 $options{position} = $position if $position;
130 0         0 return $self->post("users/$user_id/playlists/$playlist_id/tracks", $tracks, %options);
131             }
132              
133 1 0   1   611 method me {
  0     0   0  
  0         0  
134 0         0 return $self->get('me/');
135             }
136              
137 1     1   1649 method _log (@strings) {
  2     2   20  
  2         7  
138 2 50       25 print join(' ', @strings) . "\n" if $self->trace;
139             }
140              
141 1 50   1   481 method _auth_headers {
  1     1   2  
  1         6  
142 1 50       8 return $self->auth ? { 'Authorization' => 'Bearer ' . $self->auth } : undef;
143             }
144              
145 1 50   1   2098 method _uri ($method, %args) {
  1     1   2  
  1         6  
  1         4  
  1         4  
146 1 50       27 my $base_uri = $method =~ /^http/ ? $method : $self->prefix . $method;
147              
148 1         12 my $uri = URI->new( $base_uri );
149 1         11915 $uri->query_param( $_, $args{$_} ) for keys %args;
150              
151 1         6 return $uri;
152             }
153              
154 1 50   1   2154 method _get_id ($type, $id) {
  1 50   1   3  
  1 50       5  
  1         4  
  1         5  
  1         2  
  1         5  
155 1         7 my @fields = split /:/, $id;
156 1 50       5 if (@fields == 3) {
157 1 50       5 warn "expected id of type $type but found type $fields[2] id" if $type ne $fields[1];
158 1         5 return $fields[2];
159             }
160              
161 0           @fields = split /\//, $id;
162 0 0         if (@fields >= 3) {
163 0 0         warn "expected id of type $type but found type $fields[-2] id" if $type ne $fields[-2];
164 0           return $fields[-1];
165             }
166              
167 0           return $id;
168             }
169              
170             1;
171              
172             =head1 NAME
173              
174             WebService::Spotify - A simple interface to the L<Spotify Web API|https://developer.spotify.com/web-api/>
175              
176             =head1 SYNOPSIS
177              
178             my $spotify = WebService::Spotify->new;
179             my $results = $spotify->search('weezer', limit => 20);
180             say $_->{name} for @{$results->{tracks}->{items}};
181            
182              
183             More examples can be found in the /eg directory.
184              
185              
186             =head1 DESCRIPTION
187              
188             =head1 METHODS
189              
190             See L<Method::Signatures> for details of the parameter spec used below.
191              
192             Refer to the L<Spotify API documentation|https://developer.spotify.com/spotify-web-api/> for details on the methods and parameters.
193              
194             Methods that take item IDs (such as the track, album and artist methods) accept URN, URL or simple ID types. The following 3 ids are all acceptable IDs:
195              
196             http://open.spotify.com/track/3HfB5hBU0dmBt8T0iCmH42
197             spotify:track:3HfB5hBU0dmBt8T0iCmH42
198             3HfB5hBU0dmBt8T0iCmH42
199              
200             The following methods are supported:
201              
202             =head2 album ($album_id)
203              
204             returns a single album given the album's ID, URN or URL
205              
206             =head2 album_tracks ($album_id)
207              
208             Get Spotify catalog information about an album's tracks
209              
210             =head2 albums (\@albums)
211              
212             returns a list of albums given the album IDs, URNs, or URLs
213              
214             =head2 artist ($artist_id)
215              
216             returns a single artist given the artist's ID, URN or URL
217              
218             =head2 artist_albums ($artist, :$album_type, :$country, :$limit = 20, :$offset = 0)
219              
220             Get Spotify catalog information about an artist’s albums
221              
222             =head2 artist_top_tracks ($artist, :$country = 'US')
223              
224             Get Spotify catalog information about an artist’s top 10 tracks by country.
225              
226             =head2 artists (\@artists)
227              
228             returns a list of artists given the artist IDs, URNs, or URLs
229              
230             =head2 me()
231              
232             returns info about me
233              
234             =head2 next ($result)
235              
236             returns the next result given a result
237              
238             =head2 previous ($result)
239              
240             returns the previous result given a result
241              
242             =head2 search ($q, limit => 10, offset => 0, type => 'track')
243              
244             searches for an item
245              
246             =head2 track ($track_id)
247              
248             returns a single track given the track's ID, URN or URL
249              
250             =head2 tracks (\@track_ids)
251              
252             returns a list of tracks given the track IDs, URNs, or URLs
253              
254             =head2 user ($user_id)
255              
256             Gets basic profile information about a Spotify User
257              
258             =head2 user_playlist ($user_id, :$playlist_id, :$fields)
259              
260             Gets playlist of a user
261              
262             =head2 user_playlist_add_tracks ($user_id, $playlist_id, $tracks, :$position)
263              
264             Adds tracks to a playlist
265              
266             =head2 user_playlist_create ($user_id, $name, :$public = 1)
267              
268             Creates a playlist for a user
269              
270             =head2 user_playlists ($user_id)
271              
272             Gets playlists of a user
273              
274              
275             =head1 AUTHOR
276              
277             Nick Langridge <nickl@cpan.org>
278              
279             =head1 CREDITS
280              
281             This module was ported from L<Spotipy|https://github.com/plamere/spotipy>, a Python wrapper for the Spotify Web API
282              
283             =head1 LICENSE
284              
285             This module is free software; you can redistribute it or
286             modify it under the same terms as Perl itself.
287              
288             =head1 SEE ALSO
289              
290             L<WebService::EchoNest> - wrapper for the EchoNest API which has some integration with the Spotify Web API
291              
292             L<Net::Spotify> - wrapper for the old Spotify metadata API
293