Tunein-Streams
view release on metacpan or search on metacpan
lib/Tunein/Streams.pm view on Meta::CPAN
YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=cut
package Tunein::Streams;
use strict;
use warnings;
#use Carp qw(croak);
use LWP::Simple qw();
use vars qw(@ISA @EXPORT $VERSION);
our $VERSION = '1.11';
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(get getBest count validFields);
$Carp::Internal{ (__PACKAGE__) }++;
sub new
{
my $class = shift;
my $url = shift;
my $attrs;
my $self = {};
return undef unless ($url);
#THIS IS A TWO-STEP FETCH. WE FIRST FETCH THE HTML FOR THE STATION'S tunein.com WEBSITE,
#PARSE IT FOR 'StreamUrl":"<//partial-url>"', THEN, (STEP 2) APPEND "http:" TO IT AND FETCH
#THAT. THE 2ND FETCH RETURNS A FILE VERY SIMILAR TO A PERL "Data::Dumper" FILE CONTAINING
#A HASH TREE COMPOSED OF AN ARRAY OF ONE OR MORE STREAM URLS ALONG WITH THEIR OTHER PROPERTIES.
#WE THEN USE A FEW REGICES TO CONVERT IT TO A TRUE PERL-EVALABLE "Data::Dumper" STRING THAT
#WE CAN THEN EVAL INTO A PERL HASH, FROM WHICH OUR get() FUNCTIONS CAN RETURN THE DESIRED
#DATA!
my $html = '';
my $wait = 1;
for (my $i=0; $i<=2; $i++) { #WE TRY THIS FETCH 3 TIMES SINCE FOR SOME REASON, DOESN'T ALWAYS RETURN RESULTS 1ST TIME?!:
$html = LWP::Simple::get($url);
last if ($html);
sleep $wait;
++$wait;
}
return undef unless ($html); #STEP 1 FAILED, INVALID STATION URL, PUNT!
my (@streams, @streamHash, $s, $html2);
$self->{'cnt'} = 0;
$self->{'total'} = '0';
$self->{'id'} = ($url =~ m#([\w\d]+)\/?$#) ? $1 : $url;
$self->{'title'} = ($html =~ m#\<title\>(.+?)\<\/title\>#) ? $1 : '';
$self->{'iconurl'} = ($html =~ m#\<meta\s+property\s*\=\s*\"og\:image\"\s+content\s*\=\"([^\"]+)#) ? $1 : '';
$self->{'imageurl'} = ($html =~ m#\"hero\"\s+id=\s*\"imgSrc\"\s+style\=\"background\-image\:\s+url\(([^\)]+)\)#) ? $1 : '';
while ($html =~ s/StreamUrl\"\:\s*\"([^\"]+)\"(\,\s*\"DirectStreams\"\:\s*\[([^\]]+)\])?//o) { #FIND ONE (OR MORE) STREAM URLS:
$s = $1;
if ($2) { #WE HAVE A DIRECT STREAM (EMBEDDED TREE), USE THAT:
$html2 = $2;
$html2 =~ s/^\,\s*\"Direct//io;
$html2 = '{ "' . $html2 . ' }';
} else { #WE HAVE A STREAM URL, FETCH TREE FROM THERE:
$s = 'http:' . $s if ($s && $s !~ m#^\w+\:\/\/#o);
$wait = 1;
for (my $i=0; $i<=2; $i++) { #WE TRY THIS FETCH 3 TIMES SINCE FOR SOME REASON, DOESN'T ALWAYS RETURN RESULTS 1ST TIME?!:
$html2 = LWP::Simple::get($s);
last if ($html);
sleep $wait;
++$wait;
}
}
$html2 =~ s/\:\s*true\b/\:1/gio; #CONVERT "true" AND "false" STRING VALUES INTO 1 & 0 RESPECTIVELY.
$html2 =~ s/\:\s*false\b/\:0/gio;
$html2 =~ s/\"\s*\:/\" =\> /go; #FIXUP TO MAKE A VALID EVAL-ABLE HASH TREE OUT OF IT:
$html2 = "\$streamHash[$self->{'cnt'}] = " . $html2;
no strict;
eval $html2; #EVAL EACH STREAM URL'S CONTENT INTO A PERL HASH REF.
use strict;
$self->{'total'} += scalar @{$streamHash[$self->{'cnt'}]->{'Streams'}};
++$self->{'cnt'}; #NUMBER OF StreamUrl's FOUND (NOT SAME AS # OF STREAMS!)
}
$self->{'streams'} = \@streamHash;
return undef unless ($self->{'cnt'}); #STEP 2 FAILED - NO PLAYABLE STREAMS FOUND, PUNT!
#SAVE WHAT PROPERTY NAMES WE HAVE (FOR $station->validFields()):
@{$self->{fields}} = ();
foreach my $field (sort keys %{${$self->{'streams'}}[0]->{'Streams'}[0]}) {
push @{$self->{fields}}, $field;
}
bless $self, $class; #BLESS IT!
return $self;
}
sub get
{
my $self = shift;
my $field = shift || 0;
my @streams = ();
my $subcnt;
if ($field) { #USER SUPPLIED A PROPERTY NAME, FETCH ONLY THAT PROPERTY, (ie. "Url"):
return ${$self->{'streams'}}[0]->{'Streams'}[0]->{$field} unless (wantarray); #USER ONLY WANTS 1ST STREAM.
for (my $i=0; $i<$self->{'cnt'}; $i++) {
no strict;
$subcnt = scalar @{${$self->{'streams'}}[$i]->{'Streams'}};
for (my $j=0; $j<$subcnt; $j++) {
push @streams, ${$self->{'streams'}}[$i]->{'Streams'}[$j]->{$field};
}
}
} else { #NO PROPERTY NAME, RETURN A HASH-REF TO ALL THE PROPERTIES:
return ${$self->{'streams'}}[0]->{'Streams'}[0] unless (wantarray); #USER ONLY WANTS 1ST STREAM.
for (my $i=0; $i<$self->{'cnt'}; $i++) {
no strict;
$subcnt = scalar @{${$self->{'streams'}}[$i]->{'Streams'}};
for (my $j=0; $j<$subcnt; $j++) {
( run in 0.436 second using v1.01-cache-2.11-cpan-71847e10f99 )