The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
# Part of get-flash-videos. See get_flash_videos for copyright.
package FlashVideo::Site::Abc;

use strict;
use FlashVideo::Utils;

sub find_video {
  my ($self, $browser, $embed_url) = @_;

  # Clips are handled differently to full episodes
  if ($browser->uri->as_string =~ m'/watch/clip/[\w\-]+/(\w+)/(\w+)/(\w+)') {
    my $show_id     = $1;
    my $playlist_id = $2;
    my $video_id    = $3;

    return handle_abc_clip($browser, $show_id, $playlist_id, $video_id);
  }

  # http://abc.go.com/watch/lost/93372/260004/the-candidate
  my $video_id;
  if ($browser->uri->as_string =~ /\/watch\/[^\/]*\/[0-9]*\/([0-9]*)/) {
    $video_id = $1;
  }

  # h is probably quality
  my $quality="432";

  $browser->get("http://ll.static.abc.com/s/videoplatform/services/1001/getflashvideo?video=$video_id&h=$quality");

  my $xml = from_xml($browser, KeyAttr => []);

  # find a host, we'll default to L3 for now
  my $hosts = $xml->{resources}->{host};
  my $host = ref $hosts eq 'ARRAY' ?
    (grep { $_->{name} == 'L3' } @$hosts)[0] :
    $hosts;

  my $rtmpurl = $xml->{protocol} . "://" . $host->{url} . "/" . $host->{app};

  my $videos = $xml->{videos}->{video};
  my $video = ref $videos eq 'ARRAY' ?
    (grep { $_->{src} =~ /^mp4:\// } @$videos)[0] :
    $videos;

  my $playpath = $video->{src};

  $browser->get("http://ll.static.abc.com/s/videoplatform/services/1000/getVideoDetails?video=$video_id");
  my $xml = from_xml($browser);
  my $title = $xml->{metadata}->{title};

  return {
    rtmp => $rtmpurl,
    playpath => $playpath,
    flv => title_to_filename($title)
  };
}

sub handle_abc_clip {
  my ($browser, $show_id, $playlist_id, $video_id) = @_;

  # Note 'limit' has been changed to 1 instead of the default of 12. This
  # ensures that only the desired video is returned. Otherwise unrelated
  # videos are returned too.

  my $abc_clip_rss_url_template =
    "http://ll.static.abc.com/vp2/ws/s/contents/1000/videomrss?" .
    "brand=001&device=001&width=644&height=362&clipId=%s" .
    "&start=0&limit=1&fk=CATEGORIES&fv=%s";
  
  my $abc_clip_rss_url = sprintf $abc_clip_rss_url_template,
                                 $video_id, $playlist_id;

  $browser->get($abc_clip_rss_url);

  if (!$browser->success) {
    die "Couldn't download ABC clip RSS: " . $browser->response->status_line;
  }

  my $xml = from_xml($browser);

  my $video_url = $xml->{channel}->{item}->{'media:content'}->{url};
  my $type      = $video_url =~ /\.mp4$/ ? 'mp4' : 'flv';

  if (!$video_url) {
    die "Couldn't determine ABC clip URL";
  }

  # Try to get a decent filename
  my $episode_name;
  if ($video_url =~ /FLF_\d+[A-Za-z]{0,5}_([^_]+)/) {
    $episode_name = $1;
  }

  my $category    = $xml->{channel}->{item}->{category};
  my $title       = $xml->{channel}->{item}->{'media:title'}->{content};

  if (ref($category) eq 'HASH' and ! keys %$category) {
    $category = '';
  }

  # Description isn't actually very long - see media:text for that for when
  # gfv has support for writing Dublin Core-compliant metadata.
  my $description = $xml->{channel}->{item}->{'media:description'}->{content};

  # Remove HTML in evil way.
  for ($category, $description, $title) {
    s/<\/?\w+>//g;
  }

  my $video_title = make_title($category, $episode_name, $title, $description);

  return $video_url, title_to_filename($video_title, $type);
}

# Produces the title, taking into account items that don't exist
sub make_title {
  return join " - ", grep /./, @_;
}

sub can_handle {
  my($self, $browser, $url) = @_;

  # This is only ABC as in the US broadcaster, not abc.net.au
  return $url && URI->new($url)->host =~ /\babc\.(?:go\.)?com$/;
}

1;