File Coverage

blib/lib/WebService/8tracks.pm
Criterion Covered Total %
statement 67 71 94.3
branch 8 10 80.0
condition 3 5 60.0
subroutine 19 20 95.0
pod 4 6 66.6
total 101 112 90.1


line stmt bran cond sub pod time code
1             package WebService::8tracks;
2 3     3   1704431 use Any::Moose;
  3         120213  
  3         20  
3              
4             =pod
5              
6             =head1 NAME
7              
8             WebService::8tracks - Handle 8tracks API
9              
10             =head1 SYNOPSIS
11              
12             use WebService::8tracks;
13              
14             my $api = WebService::8tracks->new;
15              
16             # explore
17             my $res = $api->mixes({ sort => 'recent' });
18             foreach my $mix (@{$res->{mixes}}) {
19             print "$mix->{user}->{name} $mix->{name} id=$mix->{id}\n";
20             }
21              
22             # listen
23             my $session = $api->create_session($res->{mixes}->[0]->{id});
24             my $res = $session->play;
25             my $media_url = $res->{set}->{track}->{url};
26             ...
27             $res = $session->next;
28             $res = $session->skip;
29              
30             # authenticated API
31             my $api = WebService::8tracks->new(username => ..., password => ...);
32             $api->fav(23); # fav a track
33              
34             =head1 DESCRIPTION
35              
36             WebService::8tracks provides Perl interface to 8tracks API.
37              
38             Currently, all response objects are almost naive hashrefs.
39              
40             =cut
41              
42             has 'username', (
43             is => 'rw',
44             isa => 'Str',
45             );
46              
47             has 'password', (
48             is => 'rw',
49             isa => 'Str',
50             );
51              
52             has 'user_agent', (
53             is => 'rw',
54             isa => 'LWP::UserAgent',
55             default => sub {
56             require LWP::UserAgent;
57             return LWP::UserAgent->new;
58             },
59             );
60              
61             __PACKAGE__->meta->make_immutable;
62              
63 3     3   2213 no Any::Moose;
  3         6  
  3         17  
64              
65             our $VERSION = '0.01';
66              
67 3     3   2444 use WebService::8tracks::Session;
  3         8  
  3         377  
68 3     3   1620 use WebService::8tracks::Response;
  3         8  
  3         105  
69              
70 3     3   3935 use JSON::XS qw(decode_json);
  3         27311  
  3         250  
71 3     3   1215 use URI::Escape qw(uri_escape uri_escape_utf8);
  3         1612  
  3         217  
72 3     3   851 use HTTP::Request;
  3         2909307  
  3         3133  
73              
74             our @CARP_NOT = ( our @ISA, 'WebService::8tracks::Session' );
75              
76             our $API_BASE_URL = 'http://8tracks.com/';
77              
78             sub api_url {
79 21     21 0 33 my ($self, $path, $qparam) = @_;
80              
81 21         52 my $url = "http://api.8tracks.com/$path.json";
82 21 100       58 if ($qparam) {
83 10 50 50     53 if (ref $qparam eq 'HASH' && scalar keys %$qparam) {
84 10         16 my @pairs;
85 10         39 while (my ($key, $value) = each %$qparam) {
86 10         24 my $pair = $key . '=';
87 10 50       37 if (utf8::is_utf8 $value) {
88 0         0 $pair .= uri_escape_utf8 $value;
89             } else {
90 10         37 $pair .= uri_escape $value;
91             }
92 10         181 push @pairs, $pair;
93             }
94 10         31 $url .= '?' . join '&', @pairs;
95             } else {
96 0         0 $url .= "?$qparam";
97             }
98             }
99              
100 21         54 return $url;
101             }
102              
103             sub request_api {
104 21     21 0 51 my ($self, $method, $path, $qparam) = @_;
105              
106 21         62 my $url = $self->api_url($path, $qparam);
107 21         130 my $req = HTTP::Request->new($method, $url);
108 21 100       22874 if ($method eq 'POST') {
109 8         46 $req->header(Content_Length => 0);
110             }
111              
112 21 100 66     627 if ($self->username && $self->password) {
113 8         49 $req->authorization_basic($self->username, $self->password);
114             }
115              
116 21         2554 my $res = $self->user_agent->request($req);
117 21         3560 my $api_response = decode_json $res->content;
118 21         866 return WebService::8tracks::Response->new($api_response);
119             }
120              
121             =head1 METHODS
122              
123             =over 4
124              
125             =item new
126              
127             my $api = WebService::8tracks->new([ username => ..., password => ... ]);
128              
129             Create API object. Pass username and password args to use methods
130             that require login (like, fav, follow).
131              
132             =item mixes([ \%qparam ])
133              
134             my $res = $api->mixes({ page => 2 });
135             my $res = $api->mixes({ q => 'miles davis' });
136              
137             List mixes.
138              
139             =cut
140              
141             sub mixes {
142 0     0 1 0 my ($self, $qparam) = @_;
143 0         0 return $self->request_api(GET => 'mixes', $qparam);
144             }
145              
146             =item user($id_or_name)
147              
148             my $res = $api->user(1);
149             my $res = $api->user('remi');
150              
151             View user info.
152              
153             =cut
154              
155             sub user {
156 1     1 1 8 my ($self, $user, $qparam) = @_;
157 1         7 return $self->request_api(GET => "users/$user", $qparam);
158             }
159              
160             =item user_mixes($id_or_name[, \%qparam ])
161              
162             my $res = $api->user_mixes(2);
163             my $res = $api->user_mixes('dp', { view => 'liked' });
164              
165             List mixes made by a user.
166              
167             =cut
168              
169             sub user_mixes {
170 1     1 1 42 my ($self, $user, $qparam) = @_;
171 1         8 return $self->request_api(GET => "users/$user/mixes", $qparam);
172             }
173              
174             sub _create_play_token {
175 1     1   2 my $self = shift;
176 1         4 my $result = $self->request_api(GET => 'sets/new');
177 1         27 return $result->{play_token};
178             }
179              
180             =item create_session($mix_id)
181              
182             my $session = $api->create_session($mix_id);
183             my $res = $session->play;
184             my $res = $session->next;
185             my $res = $session->skip;
186              
187             Start playing mix. Returns a WebService::8tracks::Session.
188              
189             =cut
190              
191             sub create_session {
192 1     1 1 11 my ($self, $mix_id) = @_;
193              
194 1         7 return WebService::8tracks::Session->new(
195             api => $self,
196             play_token => $self->_create_play_token,
197             mix_id => $mix_id,
198             );
199             }
200              
201             =item like / unlike / toggle_like($mix_id)
202              
203             my $res = $api->toggle_like($mix_id);
204              
205             Like/unlike/toggle_like a mix. Requires username and password.
206              
207             =cut
208              
209             foreach my $like (qw(like unlike toggle_like)) {
210             my $code = sub {
211 1     1   14 my ($self, $mix_id) = @_;
212 1         6 return $self->request_api(POST => "mixes/$mix_id/$like");
213             };
214 3     3   32 no strict 'refs';
  3         9  
  3         434  
215             *$like = $code;
216             }
217              
218             =item fav / unfav / toggle_fav($track_id)
219              
220             my $res = $api->fav($track_id);
221              
222             Fav/unfav/toggle_fav a track. Requires username and password.
223              
224             =cut
225              
226             foreach my $fav (qw(fav unfav toggle_fav)) {
227             my $code = sub {
228 3     3   86 my ($self, $track_id) = @_;
229 3         21 return $self->request_api(POST => "tracks/$track_id/$fav");
230             };
231 3     3   16 no strict 'refs';
  3         6  
  3         353  
232             *$fav = $code;
233             }
234              
235             =item follow / unfollow / toggle_follow($user_id)
236              
237             my $res = $api->follow($user_id);
238              
239             Follow/unfollow/toggle_follow a user. Requires username and password.
240              
241             =cut
242              
243             foreach my $follow (qw(follow unfollow toggle_follow)) {
244             my $code = sub {
245 4     4   61 my ($self, $user_id) = @_;
246 4         24 return $self->request_api(POST => "users/$user_id/$follow");
247             };
248 3     3   16 no strict 'refs';
  3         14  
  3         275  
249             *$follow = $code;
250             }
251              
252             =back
253              
254             =cut
255              
256             1;
257              
258             __END__