summaryrefslogtreecommitdiff
path: root/PLUGINS/src/sky/getskyepg.pl
diff options
context:
space:
mode:
Diffstat (limited to 'PLUGINS/src/sky/getskyepg.pl')
-rwxr-xr-xPLUGINS/src/sky/getskyepg.pl200
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;
+}
+
+#---------------------------------------------------------------------------