diff options
Diffstat (limited to 'PLUGINS/src/sky/getskyepg.pl')
-rwxr-xr-x | PLUGINS/src/sky/getskyepg.pl | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/PLUGINS/src/sky/getskyepg.pl b/PLUGINS/src/sky/getskyepg.pl new file mode 100755 index 0000000..7fd7bd0 --- /dev/null +++ b/PLUGINS/src/sky/getskyepg.pl @@ -0,0 +1,200 @@ +#!/usr/bin/perl + +# getskyepg.pl: Get EPG data from Sky's web pages +# +# Connects to a running VDR instance via SVDRP, gets the channel data +# for the Sky channels and connects to Sky's web pages to extract the +# EPG data for these channels. The result is sent to VDR via SVDRP. +# +# See the README file for copyright information and how to reach the author. +# +# $Id: getskyepg.pl 1.1 2002/11/10 10:05:17 kls Exp $ + +use Getopt::Std; +use Time::Local; + +$Usage = qq{ +Usage: $0 [options] + +Options: -d hostname destination hostname (default: localhost) + -p port SVDRP port number (default: 2001) + -S source channel source (default: S28.2E) + -D days days to get EPG for (1..7, default: 2) +}; + +die $Usage if (!getopts("d:D:hp:S:") || $opt_h); + +$Dest = $opt_d || "localhost"; +$Port = $opt_p || 2001; +$Source = $opt_S || "S28.2E"; +$Days = $opt_D || 2; + +$SkyWebPage = "www.ananova.com/tv/frontpage.html"; +$WGET = "/usr/bin/wget -q -O-"; +$LOGGER = "/usr/bin/logger -t SKYEPG"; + +$DST = 0; ##XXX TODO find out whether DST is active! +$SecsInDay = 86400; + +$MaxFrequency = 1000; +$idxName = 0; +$idxFrequency = 1; +$idxSource = 3; +$idxSid = 9; + +Error("days out of range: $Days") unless (1 <= $Days && $Days <= 7); + +sub Log +{ + system("$LOGGER '@_'"); +} + +sub Error +{ + Log(@_); + die "$0: @_\n"; +} + +sub GetChannels +{ + SVDRPsend("LSTC"); + my @channels = (); + for (SVDRPreceive(250)) { + my @a = split(':', substr($_, 4)); + if ($a[$idxSource] eq $Source && $a[$idxFrequency] < $MaxFrequency) { + push(@channels, [@a]); + } + } + return @channels; +} + +sub GetPage +{ + my $channel = shift; + my $day = shift; + my $url = "$SkyWebPage?c=$channel&day=day$day"; + Log("reading $url"); + my @page = split("\n", `$WGET '$url'`); + Log("received " . ($#page + 1) . " lines"); + return @page; +} + +# In order to get the duration we need to buffer the last event: +$Id = ""; +$Time = 0; +$Title = ""; +$Episode = ""; +$Descr = ""; + +sub GetEpgData +{ + my ($channel, $channelID) = @_; + my $numEvents = 0; + SVDRPsend("C $channelID"); + $Time = 0; + for $day (1 .. $Days) { + my $dt = 0; + my $ap = ""; + my @page = GetPage($channel, $day); + for $line (@page) { + if ($line =~ /^<\/tr><tr /) { + # extract information: + my ($time, $title, $episode, $descr) = ($line =~ /^.*?<b>(.*?)<\/b>.*?<b>(.*?)<\/b> *(<i>.*?<\/i>)? *(.*?) *<\/small>/); + my ($h, $m, $a) = ($time =~ /([0-9]+)\.([0-9]+)(.)m/); + # handle am/pm: + $dt = $SecsInDay if ($ap eq "p" && $a eq "a"); + $ap = $a; + $h += 12 if ($a eq "p" && $h < 12); + $h -= 12 if ($a eq "a" && $h == 12); + # convert to time_t: + my @gmt = gmtime; + $gmt[0] = 0; # seconds + $gmt[1] = $m; # minutes + $gmt[2] = $h; # hours + $time = timegm(@gmt) + ($day - 1) * $SecsInDay + $dt + $DST; + # create EPG data: + if ($Time) { + $duration = $time - $Time; + SVDRPsend("E $Id $Time $duration"); + SVDRPsend("T $Title"); + SVDRPsend("S $Episode"); + SVDRPsend("D $Descr"); + SVDRPsend("e"); + $numEvents++; + } + # buffer the last event: + $Id = $time / 60 % 0xFFFF; # this gives us unique ids for every minute of over 6 weeks + $Time = $time; + ($Title = $title) =~ s/<[^>]+>//g; + ($Episode = $episode) =~ s/<[^>]+>//g; + ($Descr = $descr) =~ s/<[^>]+>//g; + } + } + } + SVDRPsend("c"); + Log("generated $numEvents EPG events"); +} + +sub ProcessEpg +{ + Log("getting Sky channel definitions"); + my @channels = GetChannels(); + Error("no Sky channels found") unless @channels; + Log("found " . ($#channels + 1) . " channels"); + for (@channels) { + my $channel = @$_[$idxSid]; + my $channelID = "@$_[$idxSource]-0-@$_[$idxFrequency]-$channel"; + Log("processing channel @$_[0]"); + SVDRPsend("PUTE"); + SVDRPreceive(354); + GetEpgData($channel, $channelID); + SVDRPsend("."); + SVDRPreceive(250); + } + Log("done"); +} + +#--------------------------------------------------------------------------- +# TODO: make this a Perl module??? What about Error()??? + +use Socket; + +$Timeout = 300; # max. seconds to wait for response + +$SIG{ALRM} = sub { Error("timeout"); }; +alarm($Timeout); + +$iaddr = inet_aton($Dest) || Error("no host: $Dest"); +$paddr = sockaddr_in($Port, $iaddr); + +$proto = getprotobyname('tcp'); +socket(SOCK, PF_INET, SOCK_STREAM, $proto) || Error("socket: $!"); +connect(SOCK, $paddr) || Error("connect: $!"); +select(SOCK); $| = 1; +SVDRPreceive(220); +ProcessEpg(); +SVDRPsend("QUIT"); + +sub SVDRPsend +{ + my $s = shift; + print SOCK "$s\r\n"; +} + +sub SVDRPreceive +{ + my $expect = shift | 0; + my @a = (); + while (<SOCK>) { + s/\s*$//; # 'chomp' wouldn't work with "\r\n" + push(@a, $_); + if (substr($_, 3, 1) ne "-") { + my $code = substr($_, 0, 3); + Error("expected SVDRP code $expect, but received $code") if ($code != $expect); + last; + } + } + return @a; +} + +#--------------------------------------------------------------------------- |