| 1 | # |
|---|
| 2 | # $Id: Videos.pm 11 2007-04-09 04:34:01Z hironori.yoshida $ |
|---|
| 3 | # |
|---|
| 4 | package WebService::YouTube::Videos; |
|---|
| 5 | use strict; |
|---|
| 6 | use warnings; |
|---|
| 7 | use version; our $VERSION = qv('1.0.1'); |
|---|
| 8 | |
|---|
| 9 | use Carp; |
|---|
| 10 | use LWP::UserAgent; |
|---|
| 11 | use WebService::YouTube::Util; |
|---|
| 12 | use WebService::YouTube::Video; |
|---|
| 13 | use XML::Simple; |
|---|
| 14 | |
|---|
| 15 | use base qw(Class::Accessor::Fast); |
|---|
| 16 | |
|---|
| 17 | __PACKAGE__->mk_accessors(qw(dev_id ua)); |
|---|
| 18 | |
|---|
| 19 | sub new { |
|---|
| 20 | my $class = shift; |
|---|
| 21 | |
|---|
| 22 | my $self = $class->SUPER::new(@_); |
|---|
| 23 | if ( !$self->dev_id ) { |
|---|
| 24 | croak 'dev_id is required'; |
|---|
| 25 | } |
|---|
| 26 | if ( !$self->ua ) { |
|---|
| 27 | $self->ua( LWP::UserAgent->new ); |
|---|
| 28 | } |
|---|
| 29 | return $self; |
|---|
| 30 | } |
|---|
| 31 | |
|---|
| 32 | sub parse_xml { |
|---|
| 33 | my ( $self, $xml ) = @_; |
|---|
| 34 | |
|---|
| 35 | my $ut_response = XMLin( $xml, ForceArray => [qw(comment channel video)] ); |
|---|
| 36 | |
|---|
| 37 | if ( !$ut_response ) { |
|---|
| 38 | carp 'invalid XML'; |
|---|
| 39 | return; |
|---|
| 40 | } |
|---|
| 41 | |
|---|
| 42 | if ( $ut_response->{status} ne 'ok' ) { |
|---|
| 43 | |
|---|
| 44 | =begin comment |
|---|
| 45 | |
|---|
| 46 | See L<http://youtube.com/dev_error_codes> and each B<API Function Reference> |
|---|
| 47 | |
|---|
| 48 | =end comment |
|---|
| 49 | |
|---|
| 50 | =cut |
|---|
| 51 | |
|---|
| 52 | carp( |
|---|
| 53 | sprintf "status: %s\ncode: %d\ndescription: %s", |
|---|
| 54 | $ut_response->{status}, |
|---|
| 55 | $ut_response->{error}->{code}, |
|---|
| 56 | $ut_response->{error}->{description} |
|---|
| 57 | ); |
|---|
| 58 | return; |
|---|
| 59 | } |
|---|
| 60 | |
|---|
| 61 | if ( exists $ut_response->{video_list} ) { |
|---|
| 62 | my $video_list = $ut_response->{video_list}->{video}; |
|---|
| 63 | my @videos; |
|---|
| 64 | foreach my $video_id ( keys %{$video_list} ) { |
|---|
| 65 | my $video = |
|---|
| 66 | WebService::YouTube::Video->new( $video_list->{$video_id} ); |
|---|
| 67 | $video->id($video_id); |
|---|
| 68 | push @videos, $video; |
|---|
| 69 | } |
|---|
| 70 | return @videos; |
|---|
| 71 | } |
|---|
| 72 | |
|---|
| 73 | if ( exists $ut_response->{video_details} ) { |
|---|
| 74 | my $video = |
|---|
| 75 | WebService::YouTube::Video->new( $ut_response->{video_details} ); |
|---|
| 76 | return $video; |
|---|
| 77 | } |
|---|
| 78 | |
|---|
| 79 | carp( sprintf '%s: unknown response at %s', |
|---|
| 80 | [ keys %{$ut_response} ]->[0], $ut_response ); |
|---|
| 81 | return; |
|---|
| 82 | } |
|---|
| 83 | |
|---|
| 84 | sub get_details { |
|---|
| 85 | my ( $self, $video_id ) = @_; |
|---|
| 86 | |
|---|
| 87 | if ( ref $video_id ) { |
|---|
| 88 | $video_id = $video_id->id; |
|---|
| 89 | } |
|---|
| 90 | my $uri = |
|---|
| 91 | WebService::YouTube::Util->rest_uri( $self->dev_id, |
|---|
| 92 | 'youtube.videos.get_details', { video_id => $video_id } ); |
|---|
| 93 | my $res = $self->ua->get($uri); |
|---|
| 94 | if ( !$res->is_success ) { |
|---|
| 95 | carp $res->status_line; |
|---|
| 96 | return; |
|---|
| 97 | } |
|---|
| 98 | my $video = $self->parse_xml( $res->content ); |
|---|
| 99 | if ( !$video ) { |
|---|
| 100 | return; |
|---|
| 101 | } |
|---|
| 102 | $video->id($video_id); |
|---|
| 103 | return $video; |
|---|
| 104 | } |
|---|
| 105 | |
|---|
| 106 | sub list_by_tag { |
|---|
| 107 | my ( $self, $tag, $fields ) = @_; |
|---|
| 108 | |
|---|
| 109 | my $uri = WebService::YouTube::Util->rest_uri( |
|---|
| 110 | $self->dev_id, |
|---|
| 111 | 'youtube.videos.list_by_tag', |
|---|
| 112 | { |
|---|
| 113 | tag => $tag, |
|---|
| 114 | %{ $fields || {} } |
|---|
| 115 | } |
|---|
| 116 | ); |
|---|
| 117 | my $res = $self->ua->get($uri); |
|---|
| 118 | if ( !$res->is_success ) { |
|---|
| 119 | carp $res->status_line; |
|---|
| 120 | return; |
|---|
| 121 | } |
|---|
| 122 | return $self->parse_xml( $res->content ); |
|---|
| 123 | } |
|---|
| 124 | |
|---|
| 125 | sub list_by_user { |
|---|
| 126 | my ( $self, $user ) = @_; |
|---|
| 127 | |
|---|
| 128 | my $uri = |
|---|
| 129 | WebService::YouTube::Util->rest_uri( $self->dev_id, |
|---|
| 130 | 'youtube.videos.list_by_user', { user => $user } ); |
|---|
| 131 | my $res = $self->ua->get($uri); |
|---|
| 132 | if ( !$res->is_success ) { |
|---|
| 133 | carp $res->status_line; |
|---|
| 134 | return; |
|---|
| 135 | } |
|---|
| 136 | return $self->parse_xml( $res->content ); |
|---|
| 137 | } |
|---|
| 138 | |
|---|
| 139 | sub list_featured { |
|---|
| 140 | my $self = shift; |
|---|
| 141 | |
|---|
| 142 | my $uri = |
|---|
| 143 | WebService::YouTube::Util->rest_uri( $self->dev_id, |
|---|
| 144 | 'youtube.videos.list_featured' ); |
|---|
| 145 | my $res = $self->ua->get($uri); |
|---|
| 146 | if ( !$res->is_success ) { |
|---|
| 147 | carp $res->status_line; |
|---|
| 148 | return; |
|---|
| 149 | } |
|---|
| 150 | return $self->parse_xml( $res->content ); |
|---|
| 151 | } |
|---|
| 152 | |
|---|
| 153 | 1; |
|---|
| 154 | |
|---|
| 155 | __END__ |
|---|
| 156 | |
|---|
| 157 | =head1 NAME |
|---|
| 158 | |
|---|
| 159 | WebService::YouTube::Videos - Perl interfece to youtube.videos.* |
|---|
| 160 | |
|---|
| 161 | =head1 VERSION |
|---|
| 162 | |
|---|
| 163 | This document describes WebService::YouTube::Videos version 1.0.1 |
|---|
| 164 | |
|---|
| 165 | =head1 SYNOPSIS |
|---|
| 166 | |
|---|
| 167 | use WebService::YouTube::Videos; |
|---|
| 168 | |
|---|
| 169 | my $api = WebService::YouTube::Videos->new( { dev_id => YOUR_DEV_ID } ); |
|---|
| 170 | |
|---|
| 171 | # Call API youtube.videos.list_featured |
|---|
| 172 | my @videos = $api->list_featured; |
|---|
| 173 | foreach my $video (@videos) { |
|---|
| 174 | # $video->isa('WebService::YouTube::Video'); |
|---|
| 175 | } |
|---|
| 176 | |
|---|
| 177 | # Call other APIs |
|---|
| 178 | my @videos = $api->list_by_user($user); |
|---|
| 179 | my @videos = $api->list_by_tag($tag); |
|---|
| 180 | |
|---|
| 181 | my $video = $api->get_details($video_id); |
|---|
| 182 | |
|---|
| 183 | # Parse XML |
|---|
| 184 | my @video = $api->parse_xml($xml); # when $xml contains <video_list> |
|---|
| 185 | my $video = $api->parse_xml($xml); # when $xml contains <video_details> |
|---|
| 186 | |
|---|
| 187 | =head1 DESCRIPTION |
|---|
| 188 | |
|---|
| 189 | This is a Perl interface to YouTube REST API. |
|---|
| 190 | |
|---|
| 191 | See B<Developer APIs> L<http://youtube.com/dev> and B<Developer API -- REST Interface> L<http://youtube.com/dev_rest> for details. |
|---|
| 192 | |
|---|
| 193 | =head1 SUBROUTINES/METHODS |
|---|
| 194 | |
|---|
| 195 | =head2 new(\%fields) |
|---|
| 196 | |
|---|
| 197 | Creates and returns a new WebService::YouTube::Videos object. |
|---|
| 198 | %fields can contain parameters enumerated in L</ACCESSORS> section. |
|---|
| 199 | |
|---|
| 200 | =head2 parse_xml($xml) |
|---|
| 201 | |
|---|
| 202 | Parses XML and returns the result. |
|---|
| 203 | $xml should be an object that L<XML::Simple> can understand. |
|---|
| 204 | |
|---|
| 205 | =head2 get_details( $video_id ) |
|---|
| 206 | |
|---|
| 207 | Returns a L<WebService::YouTube::Video> object. |
|---|
| 208 | $video_id is an ID of the video which you want to get details. |
|---|
| 209 | |
|---|
| 210 | See L<http://youtube.com/dev_api_ref?m=youtube.videos.get_details> for details. |
|---|
| 211 | |
|---|
| 212 | =head2 list_by_tag( $tag, \%fields ) |
|---|
| 213 | |
|---|
| 214 | Returns an array of L<WebService::YouTube::Video> object. |
|---|
| 215 | $tag is a keyword string separated by a space. |
|---|
| 216 | %fields can contain the optional parameters. |
|---|
| 217 | |
|---|
| 218 | =over |
|---|
| 219 | |
|---|
| 220 | =item page |
|---|
| 221 | |
|---|
| 222 | 1 <= page |
|---|
| 223 | |
|---|
| 224 | =item per_page |
|---|
| 225 | |
|---|
| 226 | per_page <= 100 (default 20) |
|---|
| 227 | |
|---|
| 228 | =back |
|---|
| 229 | |
|---|
| 230 | See L<http://youtube.com/dev_api_ref?m=youtube.videos.list_by_tag> for details. |
|---|
| 231 | |
|---|
| 232 | =head2 list_by_user( $user ) |
|---|
| 233 | |
|---|
| 234 | Returns an array of L<WebService::YouTube::Video> object. |
|---|
| 235 | $tag is a keyword string separated by a space. |
|---|
| 236 | %fields can contain optional parameters. |
|---|
| 237 | |
|---|
| 238 | See L<http://youtube.com/dev_api_ref?m=youtube.videos.list_by_user> for details. |
|---|
| 239 | |
|---|
| 240 | =head2 list_featured( ) |
|---|
| 241 | |
|---|
| 242 | Returns an array of L<WebService::YouTube::Video> object. |
|---|
| 243 | |
|---|
| 244 | See L<http://youtube.com/dev_api_ref?m=youtube.videos.list_featured> for details. |
|---|
| 245 | |
|---|
| 246 | =head2 ACCESSORS |
|---|
| 247 | |
|---|
| 248 | =head3 dev_id |
|---|
| 249 | |
|---|
| 250 | Developer ID |
|---|
| 251 | |
|---|
| 252 | =head3 ua |
|---|
| 253 | |
|---|
| 254 | L<LWP::UserAgent> object |
|---|
| 255 | |
|---|
| 256 | =head1 DIAGNOSTICS |
|---|
| 257 | |
|---|
| 258 | =over |
|---|
| 259 | |
|---|
| 260 | =item dev_id is required |
|---|
| 261 | |
|---|
| 262 | Developer ID is required when you call API of YouTube. |
|---|
| 263 | |
|---|
| 264 | =item invalid XML |
|---|
| 265 | |
|---|
| 266 | The XML is not a YouTube's XML. |
|---|
| 267 | |
|---|
| 268 | =item unknown response |
|---|
| 269 | |
|---|
| 270 | The ut_response is neither <video_list> nor <video_details>. |
|---|
| 271 | |
|---|
| 272 | =back |
|---|
| 273 | |
|---|
| 274 | =head1 CONFIGURATION AND ENVIRONMENT |
|---|
| 275 | |
|---|
| 276 | WebService::YouTube::Videos requires no configuration files or environment variables. |
|---|
| 277 | |
|---|
| 278 | =head1 DEPENDENCIES |
|---|
| 279 | |
|---|
| 280 | L<Class::Accessor::Fast>, L<LWP::UserAgent>, L<XML::Simple>, L<WebService::YouTube::Util>, L<WebService::YouTube::Video> |
|---|
| 281 | |
|---|
| 282 | =head1 INCOMPATIBILITIES |
|---|
| 283 | |
|---|
| 284 | None reported. |
|---|
| 285 | |
|---|
| 286 | =head1 BUGS AND LIMITATIONS |
|---|
| 287 | |
|---|
| 288 | No bugs have been reported. |
|---|
| 289 | |
|---|
| 290 | Please report any bugs or feature requests to |
|---|
| 291 | C<bug-webservice-youtube@rt.cpan.org>, or through the web interface at |
|---|
| 292 | L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=WebService-YouTube>. |
|---|
| 293 | I will be notified, and then you'll automatically be notified of progress on |
|---|
| 294 | your bug as I make changes. |
|---|
| 295 | |
|---|
| 296 | =head1 AUTHOR |
|---|
| 297 | |
|---|
| 298 | Hironori Yoshida <yoshida@cpan.org> |
|---|
| 299 | |
|---|
| 300 | =head1 LICENSE AND COPYRIGHT |
|---|
| 301 | |
|---|
| 302 | Copyright 2006, Hironori Yoshida <yoshida@cpan.org>. All rights reserved. |
|---|
| 303 | |
|---|
| 304 | This program is free software; you can redistribute it and/or modify it |
|---|
| 305 | under the same terms as Perl itself. See L<perlartistic>. |
|---|
| 306 | |
|---|
| 307 | =cut |
|---|