| blib/lib/WWW/TV/Episode.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % | 
| statement | 49 | 157 | 31.2 | 
| branch | 19 | 64 | 29.6 | 
| condition | 5 | 15 | 33.3 | 
| subroutine | 12 | 36 | 33.3 | 
| pod | 19 | 19 | 100.0 | 
| total | 104 | 291 | 35.7 | 
| line | stmt | bran | cond | sub | pod | time | code | 
|---|---|---|---|---|---|---|---|
| 1 | =head1 NAME | ||||||
| 2 | |||||||
| 3 | WWW::TV::Episode - Parse TV.com for TV Episode information. | ||||||
| 4 | |||||||
| 5 | =head1 SYNOPSIS | ||||||
| 6 | |||||||
| 7 | use WWW::TV::Episode qw(); | ||||||
| 8 | my $episode = WWW::TV::Series->new(id => '475567'); | ||||||
| 9 | |||||||
| 10 | # with optional paramers | ||||||
| 11 | |||||||
| 12 | print $episode->summary; | ||||||
| 13 | |||||||
| 14 | =head1 DESCRIPTION | ||||||
| 15 | |||||||
| 16 | The L | ||||||
| 17 | L | ||||||
| 18 | by name, so I haven't implemented it. It is probably possible to do so if you | ||||||
| 19 | populate a series object and grep $series->episodes for the episode name you | ||||||
| 20 | are searching for. | ||||||
| 21 | |||||||
| 22 | =head1 METHODS | ||||||
| 23 | |||||||
| 24 | =cut | ||||||
| 25 | |||||||
| 26 | package WWW::TV::Episode; | ||||||
| 27 | 1 | 1 | 876 | use strict; | |||
| 1 | 3 | ||||||
| 1 | 43 | ||||||
| 28 | 1 | 1 | 5 | use warnings; | |||
| 1 | 2 | ||||||
| 1 | 70 | ||||||
| 29 | |||||||
| 30 | our $VERSION = '0.14'; | ||||||
| 31 | |||||||
| 32 | 1 | 1 | 17 | use Carp qw(croak); | |||
| 1 | 2 | ||||||
| 1 | 52 | ||||||
| 33 | 1 | 1 | 4 | use LWP::UserAgent qw(); | |||
| 1 | 2 | ||||||
| 1 | 2355 | ||||||
| 34 | |||||||
| 35 | =head2 new | ||||||
| 36 | |||||||
| 37 | The new() method is the constructor. It takes the id of the show | ||||||
| 38 | assuming you have previously looked that up. | ||||||
| 39 | |||||||
| 40 | # default usage | ||||||
| 41 | my $episode = WWW::TV::Episode->new(id => 924072); | ||||||
| 42 | |||||||
| 43 | # change user-agent from the default of "libwww-perl/#.##" | ||||||
| 44 | my $episode = WWW::TV::Episode->new(id => 924072, agent => 'WWW::TV'); | ||||||
| 45 | |||||||
| 46 | It also (optionally) takes the name of the episode. This is not used | ||||||
| 47 | in any way to search for the episode, but is used as initial data | ||||||
| 48 | population for that field so that the html isn't parsed if you only | ||||||
| 49 | want an object with the name. This is used by the L | ||||||
| 50 | object to populate a big array of episodes that have names without | ||||||
| 51 | needing to fetch any pages. | ||||||
| 52 | |||||||
| 53 | # pre-populate episode name | ||||||
| 54 | my $episode = WWW::TV::Episode->new(id => 924072, name => 'Run!'); | ||||||
| 55 | |||||||
| 56 | =cut | ||||||
| 57 | |||||||
| 58 | sub new { | ||||||
| 59 | 2 | 50 | 2 | 1 | 1370 | my $class = ref $_[0] ? ref(shift) : shift; | |
| 60 | |||||||
| 61 | 2 | 3 | my %data; | ||||
| 62 | |||||||
| 63 | 2 | 50 | 11 | if (@_ == 1) { | |||
| 50 | |||||||
| 64 | 0 | 0 | $data{id} = shift; | ||||
| 65 | } | ||||||
| 66 | elsif (scalar(@_) % 2 == 0) { | ||||||
| 67 | 2 | 7 | %data = @_; | ||||
| 68 | } | ||||||
| 69 | |||||||
| 70 | 2 | 50 | 6 | croak 'No id given to constructor' unless exists $data{id}; | |||
| 71 | 2 | 50 | 33 | 23 | croak "Invalid id: $data{id}" unless ($data{id} =~ /^\d+$/ && $data{id}); | ||
| 72 | |||||||
| 73 | 2 | 100 | 26 | return bless { | |||
| 74 | id => $data{id}, | ||||||
| 75 | name => $data{name}, | ||||||
| 76 | _agent => $data{agent}, | ||||||
| 77 | _site => $data{site}, | ||||||
| 78 | filled => { | ||||||
| 79 | id => 1, | ||||||
| 80 | $data{name} | ||||||
| 81 | ? (name => 1) | ||||||
| 82 | : (), | ||||||
| 83 | }, | ||||||
| 84 | }, $class; | ||||||
| 85 | } | ||||||
| 86 | |||||||
| 87 | =head2 id | ||||||
| 88 | |||||||
| 89 | The ID of this episode, according to TV.com | ||||||
| 90 | |||||||
| 91 | =cut | ||||||
| 92 | |||||||
| 93 | sub id { | ||||||
| 94 | 3 | 3 | 1 | 59 | my $self = shift; | ||
| 95 | |||||||
| 96 | 3 | 414 | return $self->{id}; | ||||
| 97 | } | ||||||
| 98 | |||||||
| 99 | =head2 name | ||||||
| 100 | |||||||
| 101 | Returns a string containing the name of the episode. | ||||||
| 102 | |||||||
| 103 | =cut | ||||||
| 104 | |||||||
| 105 | sub name { | ||||||
| 106 | 1 | 1 | 1 | 2 | my $self = shift; | ||
| 107 | |||||||
| 108 | 1 | 50 | 5 | unless (exists $self->{filled}->{name}) { | |||
| 109 | 0 | 0 | $self->{filled}->{name} = 1; | ||||
| 110 | 0 | 0 | ($self->{name}) = $self->_html =~ m{ | ||||
| 111 | (.*)\n | ||||||
| 112 | \s* | ||||||
| 113 | }x; | ||||||
| 114 | } | ||||||
| 115 | |||||||
| 116 | 1 | 5 | return $self->{name}; | ||||
| 117 | } | ||||||
| 118 | |||||||
| 119 | =head2 summary | ||||||
| 120 | |||||||
| 121 | Returns a string containing basic information about this series. | ||||||
| 122 | |||||||
| 123 | =cut | ||||||
| 124 | |||||||
| 125 | sub summary { | ||||||
| 126 | 1 | 1 | 1 | 2 | my $self = shift; | ||
| 127 | |||||||
| 128 | 1 | 50 | 10 | unless (exists $self->{filled}->{summary}) { | |||
| 129 | 1 | 3 | $self->{filled}->{summary} = 1; | ||||
| 130 | 1 | 4 | ($self->{summary}) = $self->_html =~ m{ | ||||
| 131 | (.*?) | ||||||
| 132 | }smx; | ||||||
| 133 | 0 | 0 | $self->{summary} =~ s/ /\n/g; | ||||
| 134 | 0 | 0 | $self->{summary} =~ s/.*?<\/a>//g; | ||||
| 135 | 0 | 0 | $self->{summary} =~ s/^\s*//; | ||||
| 136 | 0 | 0 | $self->{summary} =~ s/\s*$//; | ||||
| 137 | } | ||||||
| 138 | |||||||
| 139 | 0 | 0 | return $self->{summary}; | ||||
| 140 | } | ||||||
| 141 | |||||||
| 142 | =head2 season_number | ||||||
| 143 | |||||||
| 144 | Returns the season number that this episode appeared in. | ||||||
| 145 | |||||||
| 146 | =cut | ||||||
| 147 | |||||||
| 148 | sub season_number { | ||||||
| 149 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 150 | |||||||
| 151 | 0 | 0 | 0 | unless (exists $self->{filled}->{season_number}) { | |||
| 152 | 0 | 0 | $self->_fill_vitals; | ||||
| 153 | } | ||||||
| 154 | |||||||
| 155 | 0 | 0 | return $self->{season_number}; | ||||
| 156 | } | ||||||
| 157 | |||||||
| 158 | =head2 episode_number | ||||||
| 159 | |||||||
| 160 | Returns the overall number of this episode. Note, this is not | ||||||
| 161 | necessarily the production order of the episodes, but is the order | ||||||
| 162 | in which they aired. | ||||||
| 163 | |||||||
| 164 | =cut | ||||||
| 165 | |||||||
| 166 | sub episode_number { | ||||||
| 167 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 168 | |||||||
| 169 | 0 | 0 | 0 | unless (exists $self->{filled}->{episode_number}) { | |||
| 170 | 0 | 0 | $self->_fill_vitals; | ||||
| 171 | } | ||||||
| 172 | |||||||
| 173 | 0 | 0 | return $self->{episode_number}; | ||||
| 174 | } | ||||||
| 175 | |||||||
| 176 | =head2 format_details ($format_str) | ||||||
| 177 | |||||||
| 178 | Returns episode details using a special format string, similar to printf: | ||||||
| 179 | %I - series ID | ||||||
| 180 | %N - series name | ||||||
| 181 | %s - season number | ||||||
| 182 | %S - season number (0-padded to two digits, if required) | ||||||
| 183 | %i - episode ID | ||||||
| 184 | %e - episode number | ||||||
| 185 | %E - episode number (0-padded to two digits, if required) | ||||||
| 186 | %n - episode name | ||||||
| 187 | %d - date episode first aired | ||||||
| 188 | |||||||
| 189 | The default format is: | ||||||
| 190 | %N.s%Se%E - %n (eg: "Heroes.s1e02 - Don't Look Back") | ||||||
| 191 | |||||||
| 192 | =cut | ||||||
| 193 | |||||||
| 194 | sub format_details { | ||||||
| 195 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 196 | |||||||
| 197 | 0 | 0 | 0 | my $format_str = shift || '%N.s%Se%E - %n'; | |||
| 198 | |||||||
| 199 | # format subs .. expecting $_[0] is $self | ||||||
| 200 | my %formats = ( | ||||||
| 201 | 0 | 0 | 0 | 'I' => sub { $_[0]->series_id }, | |||
| 202 | 0 | 0 | 0 | 'N' => sub { $_[0]->series->name }, | |||
| 203 | 0 | 0 | 0 | 's' => sub { $_[0]->season_number }, | |||
| 204 | 0 | 0 | 0 | 'S' => sub { sprintf('%02d', $_[0]->season_number) }, | |||
| 205 | 0 | 0 | 0 | 'i' => sub { $_[0]->id }, | |||
| 206 | 0 | 0 | 0 | 'e' => sub { $_[0]->episode_number }, | |||
| 207 | 0 | 0 | 0 | 'E' => sub { sprintf('%02d', $_[0]->episode_number) }, | |||
| 208 | 0 | 0 | 0 | 'n' => sub { $_[0]->name }, | |||
| 209 | 0 | 0 | 0 | 'd' => sub { $_[0]->first_aired }, | |||
| 210 | 0 | 0 | ); | ||||
| 211 | |||||||
| 212 | # substitution | ||||||
| 213 | 0 | 0 | $format_str =~ | ||||
| 214 | s/ | ||||||
| 215 | # look for single character format specifier | ||||||
| 216 | %([a-zA-Z]) | ||||||
| 217 | / | ||||||
| 218 | # use format sub if found, otherwise leave as-is | ||||||
| 219 | 0 | 0 | 0 | $formats{$1} ? $formats{$1}->($self) : "\%$1" | |||
| 220 | |||||||
| 221 | /sgex; | ||||||
| 222 | |||||||
| 223 | 0 | 0 | return $format_str; | ||||
| 224 | } | ||||||
| 225 | |||||||
| 226 | =head2 first_aired | ||||||
| 227 | |||||||
| 228 | Returns a string of the date this episode first aired in ISO 8601 (yyyy-mm-dd) format. | ||||||
| 229 | |||||||
| 230 | =cut | ||||||
| 231 | |||||||
| 232 | sub first_aired { | ||||||
| 233 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 234 | |||||||
| 235 | 0 | 0 | 0 | unless (exists $self->{filled}->{first_aired}) { | |||
| 236 | 0 | 0 | $self->_fill_vitals; | ||||
| 237 | } | ||||||
| 238 | |||||||
| 239 | 0 | 0 | return $self->{first_aired}; | ||||
| 240 | } | ||||||
| 241 | |||||||
| 242 | =head2 stars | ||||||
| 243 | |||||||
| 244 | Returns a list of the stars that appeared in this episode. | ||||||
| 245 | |||||||
| 246 | # in scalar context, returns a comma-delimited string | ||||||
| 247 | my $stars = $episode->stars; | ||||||
| 248 | |||||||
| 249 | # in array context, returns an array | ||||||
| 250 | my @stars = $episode->stars; | ||||||
| 251 | |||||||
| 252 | =cut | ||||||
| 253 | |||||||
| 254 | sub stars { | ||||||
| 255 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 256 | |||||||
| 257 | 0 | 0 | 0 | unless (exists $self->{filled}->{stars}) { | |||
| 258 | 0 | 0 | my ($stars) = $self->_html =~ m{ | ||||
| 259 | 
 | ||||||
| 260 |  | ||||||
| 261 | ( | ||||||
| 262 | |||||||
| 263 | }x; | ||||||
| 264 | |||||||
| 265 | 0 | 0 | $self->{stars} = $self->_parse_people($stars); | ||||
| 266 | 0 | 0 | $self->{filled}->{stars} = 1; | ||||
| 267 | } | ||||||
| 268 | |||||||
| 269 | 0 | 0 | return $self->{stars}; | ||||
| 270 | } | ||||||
| 271 | |||||||
| 272 | =head2 guest_stars | ||||||
| 273 | |||||||
| 274 | Returns a list of the guest stars that appeared in this episode. | ||||||
| 275 | |||||||
| 276 | # in scalar context, returns a comma-delimited string | ||||||
| 277 | my $guest_stars = $episode->guest_stars; | ||||||
| 278 | |||||||
| 279 | # in array context, returns an array | ||||||
| 280 | my @guest_stars = $episode->guest_stars; | ||||||
| 281 | |||||||
| 282 | =cut | ||||||
| 283 | |||||||
| 284 | sub guest_stars { | ||||||
| 285 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 286 | |||||||
| 287 | 0 | 0 | 0 | unless (exists $self->{filled}->{guest_stars}) { | |||
| 288 | 0 | 0 | my ($stars) = $self->_html =~ m{ | ||||
| 289 | 
 | ||||||
| 290 |  | ||||||
| 291 | ( | ||||||
| 292 | |||||||
| 293 | }x; | ||||||
| 294 | |||||||
| 295 | 0 | 0 | $self->{guest_stars} = $self->_parse_people($stars); | ||||
| 296 | 0 | 0 | $self->{filled}->{guest_stars} = 1; | ||||
| 297 | } | ||||||
| 298 | |||||||
| 299 | 0 | 0 | return $self->{guest_stars}; | ||||
| 300 | } | ||||||
| 301 | |||||||
| 302 | =head2 recurring_roles | ||||||
| 303 | |||||||
| 304 | Returns a list of the people who have recurring roles | ||||||
| 305 | that appeared in this episode | ||||||
| 306 | |||||||
| 307 | # in scalar context, returns a comma-delimited string | ||||||
| 308 | my $recurring_roless = $episode->recurring_roless; | ||||||
| 309 | |||||||
| 310 | # in array context, returns an array | ||||||
| 311 | my @recurring_roless = $episode->recurring_roless; | ||||||
| 312 | |||||||
| 313 | =cut | ||||||
| 314 | |||||||
| 315 | sub recurring_roles { | ||||||
| 316 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 317 | |||||||
| 318 | 0 | 0 | 0 | unless (exists $self->{filled}->{recurring_roles}) { | |||
| 319 | 0 | 0 | my ($stars) = $self->_html =~ m{ | ||||
| 320 | 
 | ||||||
| 321 |  | ||||||
| 322 | ( | ||||||
| 323 | |||||||
| 324 | }x; | ||||||
| 325 | |||||||
| 326 | 0 | 0 | $self->{recurring_roles} = $self->_parse_people($stars); | ||||
| 327 | 0 | 0 | $self->{filled}->{recurring_roles} = 1; | ||||
| 328 | } | ||||||
| 329 | |||||||
| 330 | 0 | 0 | return $self->{recurring_roles}; | ||||
| 331 | } | ||||||
| 332 | |||||||
| 333 | sub _parse_people { | ||||||
| 334 | 0 | 0 | 0 | my $self = shift; | |||
| 335 | 0 | 0 | 0 | my $stars = shift or return; | |||
| 336 | |||||||
| 337 | 0 | 0 | my @stars; | ||||
| 338 | 0 | 0 | for my $star (split /<\/dd>/, $stars) { | ||||
| 339 | 0 | 0 | 0 | next unless $star =~ m{(.*?)}; | |||
| 340 | 0 | 0 | push @stars, $1; | ||||
| 341 | } | ||||||
| 342 | |||||||
| 343 | 0 | 0 | return join(', ', @stars); | ||||
| 344 | } | ||||||
| 345 | |||||||
| 346 | =head2 writers | ||||||
| 347 | |||||||
| 348 | Returns a list of the people that wrote this episode. | ||||||
| 349 | |||||||
| 350 | # in scalar context, returns a comma-delimited string | ||||||
| 351 | my $writers = $episode->writers; | ||||||
| 352 | |||||||
| 353 | # in array context, returns an array | ||||||
| 354 | my @writers = $episode->writers; | ||||||
| 355 | |||||||
| 356 | =cut | ||||||
| 357 | |||||||
| 358 | sub writers { | ||||||
| 359 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 360 | |||||||
| 361 | 0 | 0 | 0 | unless (exists $self->{filled}->{writers}) { | |||
| 362 | 0 | 0 | my ($writers) = $self->_html =~ m{ | ||||
| 363 | 
 | ||||||
| 364 |  | ||||||
| 365 | ( | ||||||
| 366 | |||||||
| 367 | }x; | ||||||
| 368 | |||||||
| 369 | 0 | 0 | $self->{writers} = $self->_parse_people($writers); | ||||
| 370 | 0 | 0 | $self->{filled}->{writers} = 1; | ||||
| 371 | } | ||||||
| 372 | |||||||
| 373 | 0 | 0 | return $self->{writers}; | ||||
| 374 | } | ||||||
| 375 | |||||||
| 376 | =head2 directors | ||||||
| 377 | |||||||
| 378 | Returns a list of the people that directed this episode. | ||||||
| 379 | |||||||
| 380 | # in scalar context, returns a comma-delimited string | ||||||
| 381 | my $directors = $episode->directors; | ||||||
| 382 | |||||||
| 383 | # in array context, returns an array | ||||||
| 384 | my @directors = $episode->directors; | ||||||
| 385 | |||||||
| 386 | =cut | ||||||
| 387 | |||||||
| 388 | sub directors { | ||||||
| 389 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 390 | |||||||
| 391 | 0 | 0 | 0 | unless (exists $self->{filled}->{directors}) { | |||
| 392 | 0 | 0 | my ($directors) = $self->_html =~ m{ | ||||
| 393 | 
 | ||||||
| 394 |  | ||||||
| 395 | ( | ||||||
| 396 | |||||||
| 397 | }x; | ||||||
| 398 | |||||||
| 399 | 0 | 0 | $self->{directors} = $self->_parse_people($directors); | ||||
| 400 | 0 | 0 | $self->{filled}->{directors} = 1; | ||||
| 401 | } | ||||||
| 402 | |||||||
| 403 | 0 | 0 | return $self->{directors}; | ||||
| 404 | } | ||||||
| 405 | |||||||
| 406 | =head2 agent ($value) | ||||||
| 407 | |||||||
| 408 | Returns the current user agent setting, and sets to $value if provided. | ||||||
| 409 | |||||||
| 410 | =cut | ||||||
| 411 | |||||||
| 412 | sub agent { | ||||||
| 413 | 6 | 6 | 1 | 488 | my $self = shift; # may be called as $self or $class | ||
| 414 | 6 | 8 | my $value = shift; | ||||
| 415 | |||||||
| 416 | 6 | 50 | 15 | if (ref $self) { | |||
| 417 | 6 | 100 | 14 | if (defined $value) { | |||
| 418 | 2 | 4 | $self->{_agent} = $value; | ||||
| 419 | } | ||||||
| 420 | 6 | 66 | 33 | return ($self->{_agent} || LWP::UserAgent::_agent); | |||
| 421 | } else { | ||||||
| 422 | 0 | 0 | 0 | return ($value || LWP::UserAgent::_agent); | |||
| 423 | } | ||||||
| 424 | } | ||||||
| 425 | |||||||
| 426 | =head2 site ($value) | ||||||
| 427 | |||||||
| 428 | Returns the current mirror site setting, and sets to $value if provided. | ||||||
| 429 | |||||||
| 430 | Default site is "www"; other options include: us, uk, au | ||||||
| 431 | |||||||
| 432 | =cut | ||||||
| 433 | |||||||
| 434 | sub site { | ||||||
| 435 | 8 | 8 | 1 | 14 | my $self = shift; # may be called as $self or $class | ||
| 436 | 8 | 11 | my $value = shift; | ||||
| 437 | |||||||
| 438 | 8 | 50 | 22 | if (ref $self) { | |||
| 439 | 8 | 100 | 19 | if (defined $value) { | |||
| 440 | 3 | 100 | 22 | if ($value =~ /^(au|uk|us|www|)$/i) { | |||
| 441 | 2 | 6 | $self->{_site} = $value; | ||||
| 442 | } else { | ||||||
| 443 | 1 | 113 | warn "Ignoring unknown site value: [$value]\n"; | ||||
| 444 | } | ||||||
| 445 | } | ||||||
| 446 | 8 | 100 | 55 | return ($self->{_site} || 'www'); | |||
| 447 | } else { | ||||||
| 448 | 0 | 0 | 0 | return ($value || 'www'); | |||
| 449 | } | ||||||
| 450 | } | ||||||
| 451 | |||||||
| 452 | =head2 url | ||||||
| 453 | |||||||
| 454 | Returns the url that was used to create this object. | ||||||
| 455 | |||||||
| 456 | =cut | ||||||
| 457 | |||||||
| 458 | sub url { | ||||||
| 459 | 1 | 1 | 1 | 2 | my $self = shift; | ||
| 460 | |||||||
| 461 | 1 | 5 | return sprintf('http://%s.tv.com/episode/%d/summary.html', $self->site, $self->id); | ||||
| 462 | } | ||||||
| 463 | |||||||
| 464 | =head2 season | ||||||
| 465 | |||||||
| 466 | Returns an array of other episodes for the same season of this series. | ||||||
| 467 | |||||||
| 468 | =cut | ||||||
| 469 | |||||||
| 470 | sub season { | ||||||
| 471 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 472 | 0 | 0 | my @episodes = $self->series->episodes( season => $self->season_number ); | ||||
| 473 | 0 | 0 | 0 | return wantarray ? @episodes : \@episodes; | |||
| 474 | } | ||||||
| 475 | |||||||
| 476 | =head2 series_id | ||||||
| 477 | |||||||
| 478 | Returns the series ID for this episode. | ||||||
| 479 | |||||||
| 480 | =cut | ||||||
| 481 | |||||||
| 482 | sub series_id { | ||||||
| 483 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 484 | |||||||
| 485 | 0 | 0 | 0 | unless (exists $self->{filled}->{series_id}) { | |||
| 486 | 0 | 0 | my ($id) = $self->_html =~ m{}; | ||||
| 487 | 0 | 0 | $self->{series_id} = $id; | ||||
| 488 | 0 | 0 | $self->{filled}->{series_id} = 1; | ||||
| 489 | } | ||||||
| 490 | |||||||
| 491 | 0 | 0 | return $self->{series_id}; | ||||
| 492 | } | ||||||
| 493 | |||||||
| 494 | =head2 series | ||||||
| 495 | |||||||
| 496 | Returns an L | ||||||
| 497 | that this episode is a part of. | ||||||
| 498 | |||||||
| 499 | =cut | ||||||
| 500 | |||||||
| 501 | sub series { | ||||||
| 502 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 503 | |||||||
| 504 | 0 | 0 | 0 | unless (exists $self->{filled}->{series}) { | |||
| 505 | 0 | 0 | 0 | if ($self->series_id) { | |||
| 506 | 0 | 0 | require WWW::TV::Series; | ||||
| 507 | 0 | 0 | $self->{series} = WWW::TV::Series->new(id => $self->series_id); | ||||
| 508 | 0 | 0 | $self->{filled}->{series} = 1; | ||||
| 509 | } else { | ||||||
| 510 | 0 | 0 | croak "Can't find series_id for this episode"; | ||||
| 511 | } | ||||||
| 512 | } | ||||||
| 513 | |||||||
| 514 | 0 | 0 | return $self->{series}; | ||||
| 515 | } | ||||||
| 516 | |||||||
| 517 | sub _fill_vitals { | ||||||
| 518 | 0 | 0 | 0 | my $self = shift; | |||
| 519 | |||||||
| 520 | 0 | 0 | ($self->{season_number}, $self->{episode_number}, $self->{first_aired}) | ||||
| 521 | = $self->_html | ||||||
| 522 | =~ m{ | ||||||
| 523 |  | ||||||
| 524 |  | ||||||
| 525 |  | ||||||
| 526 |  | ||||||
| 527 | (?: | ||||||
| 528 | (?: | ||||||
| 529 | |||||||
| 530 | }sx; | ||||||
| 531 | |||||||
| 532 | 0 | 0 | $self->{filled}->{$_} = 1 for qw(episode_number season_number first_aired); | ||||
| 533 | |||||||
| 534 | 0 | 0 | return $self->_parse_first_aired; | ||||
| 535 | } | ||||||
| 536 | |||||||
| 537 | sub _parse_first_aired { | ||||||
| 538 | 0 | 0 | 0 | my $self = shift; | |||
| 539 | |||||||
| 540 | 0 | 0 | 0 | if (not defined $self->{first_aired}) { | |||
| 541 | 0 | 0 | $self->{first_aired} = 'n/a'; | ||||
| 542 | } | ||||||
| 543 | |||||||
| 544 | 0 | 0 | 0 | return if $self->{first_aired} eq 'n/a'; | |||
| 545 | |||||||
| 546 | 0 | 0 | my ($month, $day, $year) = split('/', $self->{first_aired}); | ||||
| 547 | 0 | 0 | $self->{first_aired} = sprintf('%04d-%02d-%02d', $year, $month, $day); | ||||
| 548 | |||||||
| 549 | 0 | 0 | return 1; | ||||
| 550 | } | ||||||
| 551 | |||||||
| 552 | sub _html { | ||||||
| 553 | 1 | 1 | 3 | my $self = shift; | |||
| 554 | |||||||
| 555 | 1 | 50 | 5 | unless ($self->{filled}->{html}) { | |||
| 556 | 1 | 4 | my $ua = LWP::UserAgent->new( agent => $self->agent ); | ||||
| 557 | 1 | 4777 | my $rc = $ua->get($self->url); | ||||
| 558 | |||||||
| 559 | 1 | 50 | 1520175 | croak sprintf('Unable to fetch page for series %s', $self->id) | |||
| 560 | unless $rc->is_success; | ||||||
| 561 | 0 | $self->{html} = | |||||
| 562 | join( | ||||||
| 563 | "\n", | ||||||
| 564 | 0 | map { s/^\s*//; s/\s*$//; $_ } | |||||
| 0 | |||||||
| 0 | |||||||
| 565 | split /\n/, $rc->content | ||||||
| 566 | ); | ||||||
| 567 | 0 | $self->{filled}->{html} = 1; | |||||
| 568 | } | ||||||
| 569 | |||||||
| 570 | 0 | return $self->{html}; | |||||
| 571 | } | ||||||
| 572 | |||||||
| 573 | 1; | ||||||
| 574 | |||||||
| 575 | __END__ |