blob: 71ba6bf034a4cc7f78b6a8d0dce586a07255f3e5 [file] [log] [blame]
# Part of get-flash-videos. See get_flash_videos for copyright.
package FlashVideo::Site::Syfy;
use strict;
use FlashVideo::Utils;
use FlashVideo::JSON;
sub make_guid {
my($self, $len) = @_;
my @chars = ('A' .. 'Z');
return join "", map { $chars[rand @chars] } 1 .. $len;
}
sub find_video {
my ($self, $browser, $embed_url, $prefs) = @_;
##
# For the Syfy website, the video player is embedded in an iframe
# the current player is from player.theplatform.com
#
# Note too that there are several other iframes in the page, mostly
# for adverts. Currently the player iframe is first but if the regexp
# below stops working, likely theres an advert iframe above it
##
my $url;
if ($browser->content =~ /<iframe\n\s*class=.*\n\s*src="([^"]*)"/) {
$browser->get($1);
if (!$browser->success) {
die "Couldn't download iframe $url: " . $browser->response->status_line;
}
if ($browser->content =~ /tp:releaseUrl="([^"]*)"/) {
$url = $1;
} else {
die "Couln't find SMIL url in " . $browser->uri->as_string;
}
$url .= 'feed=All%20Videos&defaultm3ubitrate=1000&manifest=f4m&format=SMIL&Tracking=true&Embedded=true';
} elsif ($browser->uri->as_string =~ m,(http://[^/]*)/.*vid:(\d+),) {
my ($host,$vid) = ($1, $2);
##
# This is a lot of heuristics, so if anything goes wrong it's
# probably in here
##
# First heuristic, the nbcParams.js file exists and gives the
# base URLs for most of the downloads
##
$browser->get($host.'/_utils/video/codebase/js/nbcParams.js');
info $browser->uri;
die "Looks like nbcParams heuristic no longer works" if (!$browser->success);
my ($json) = from_json($browser->content);
$host =~ m,https?://www\.([^\.]*).com,;
$host = $1;
my $feedurl;
foreach (@{$json->{channels}}) {
info "found name ".$_->{name};
if ($_->{name} eq $host) {
$feedurl = $_->{feed}->{url};
last;
}
}
die "Couldn't find feed URL for $host" if (!defined($feedurl));
##
# another nasty hairy heuristic
##
$feedurl .= '?&form=json&fields=guid,title,description,:subtitle,content,thumbnails,categories,:fullEpisode,:disallowSharing%20&fileFields=url,duration,width,height,contentType,fileSize,format,isDefault&byGuid='.$vid;
$browser->get($feedurl);
die "Feed URL heuristic failed" if (!$browser->success);
$json = from_json($browser->content);
##
# the reason for this bizzarre sequence is that the json seems
# to contain a set of media descriptors and resolutions, but
# the link file urls are all for the same f4m manifest, so
# just pull out the firs one
##
$url = $json->{entries}->[0]->{'media$content'}->[0]->{'plfile$url'};
die "Failed to parse feedurl json" if (!$url);
$url .= '&manifest=f4m&format=SMIL&Tracking=true&Embedded=true';
} else {
die "Couln't recognise Syfy video in " . $browser->uri->as_string;
}
##
# OK, now we have the url, try to find the F4V manifest. First we
# need the SMIL data
##
$browser->get($url);
if (!$browser->success) {
die "Couldn't download SMIL $url: " . $browser->response->status_line;
}
##
# SMIL is really just XML with a certain schema
##
my $xml = from_xml($browser->content);
my $seq = $xml->{body}->{seq};
my $par = $seq;
$par = $seq->{par} if (defined($seq->{par}));
my $vid;
if (ref $par eq 'HASH') {
$vid = $par->{video};
} else {
foreach (@{$par}) {
if (defined($_->{video})) {
$vid = $_->{video};
last;
}
}
}
die "Failed to find video tag in ".$url if (!defined($vid));
##
# now we have to slap on a 12 letter GUID and the version of hdcore
##
my $auth = 'g='.$self->make_guid(12);
$url = $vid->{src}.'?'.$auth."&hdcore=3.0.3";
my $title = $vid->{title};
return {
downloader => 'f4m',
manifest => $url,
flv => title_to_filename($title),
};
}
sub can_handle {
my($self, $browser, $url) = @_;
return $url =~ m,http://www\.defiance\.com/,i
|| $url =~ m,http://www\.syfy\.com/,i;
}
1;