#!/usr/bin/perl

# fetcher.pl --- fetch TV program listings for potatoe.el.

# Copyright (C) 1999 Mark Probst

# Author: Mark Probst <schani@unix.cslab.tuwien.ac.at>
# Maintainer: Mark Probst <schani@unix.cslab.tuwien.ac.at>
# Version: 0.4

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, you can either send email to this
# program's maintainer or write to: The Free Software Foundation,
# Inc.; 675 Massachusetts Avenue; Cambridge, MA 02139, USA.

# HTML output code contributed by
#   Gottfried Szing <e9625460@stud3.tuwien.ac.at>

use strict;

use LWP;
use Getopt::Long;

sub lisp {
    my $str = shift;

    if (length($str) == 0) {
	return "()";
    } else {
	$str =~ s/\"/\\\"/g;
	return "\"$str\"";
    }
}

my @categories = ( "fil", "inf", "spo", "ser", "nac", "unt", "pol", "kun", "kin" );

# change this list to include the stations you watch!
my @stations = ( "ARD", "ZDF", "RTL", "SAT.1", "PRO 7", "KABEL 1", "RTL 2", "S-RTL", "ARTE",
		 "TM3", "VOX", "3SAT", "NORD", "BAYERN", "MDR", "SW III", "MTV", "VIVA", "DSF",
		 "N-TV", "E-NEWS", "KINDER KANAL", "CNN", "NBC", "TNT", "CARTOON", "ORF1", "ORF2" );

my %catnames = ( "fil", "Filme",
		 "inf", "Information",
		 "spo", "Sport",
		 "ser", "Serien",
		 "nac", "Nachrichten",
		 "unt", "Unterhaltung",
		 "pol", "Politik",
		 "kun", "Kunst\&Kultur",
		 "kin", "Kinder" );

my %catcolor = ( "", "#ffffff",
		 "fil", "#0fffff",
		 "inf", "#00808F",
		 "spo", "#00ff00",
		 "ser", "#00ffFF",
		 "nac", "#ff0000",
		 "unt", "#ff00FF",
		 "pol", "#ffff00",
		 "kun", "#ffffFF",
		 "kin", "#f0f0f0" );

sub movie_length {
    return $_[0]*60+$_[1];
}

sub movie_table_data {
    my ($bh, $bm, $eh, $em, $ot, $oc) = @_;
    return if ($bh == $eh) && ($bm == $em);
	
    my $e = movie_length($eh, $em);
    my $b = movie_length($bh, $bm);

    my $length	= int(($e - $b)/5);

    $ot = "&nbsp;" if ($ot eq "");

    return "<td nowrap bgcolor=$catcolor{$oc} colspan=$length>$bh:$bm $ot</td>\n";
}

sub usage {
    print STDERR "Usage: $0 [OPTION]...
Fetch TV program from www.tvtoday.de.
At least one of --emacs and --html must be specified.

  --help            display this help and exit
  --emacs=DIR       generate Emacs potatoe files in DIR
  --html=DIR        generate HTML output in DIR
";
    exit(1);
}

my $emacs_dir;
my $html_dir;

if (!GetOptions("help", \&usage,
		"emacs=s", \$emacs_dir,
		"html=s", \$html_dir)) {
    usage();
}

if (!$emacs_dir && !$html_dir) {
    print STDERR "At least one of --emacs and --html must be specified!\n";
    exit(1);
}

if ($emacs_dir && !(-d $emacs_dir && -w $emacs_dir)) {
    print STDERR "$emacs_dir is not a writable directory!\n";
    exit(1);
}
if ($html_dir && !(-d $html_dir && -w $html_dir)) {
    print STDERR "$html_dir is not a writable directory!\n";
    exit(1);
}

my $ua = LWP::UserAgent->new;

my $time = time;

for (my $day = 0; $day < 7; ++$day) {
    my $daytime = $time + $day * 3600 * 24;

    my ($dummy, $dummy, $dummy, $mday, $month, $year, $wday, $yday, $dummy) = localtime($daytime);

    my $emacs_filename;
    my $html_cat_filename;

    my @lines_time;
    my @lines_overview;

    if ($emacs_dir) {
	$emacs_filename = sprintf("%s/tv-%d-%02d-%02d", $emacs_dir, 1900 + $year, $month + 1, $mday);
    }
    if ($html_dir) {
	$html_cat_filename = sprintf("%s/tv-%d-%02d-%02d-cat.html", $html_dir, 1900 + $year, $month + 1, $mday);
    }

    if ((!$emacs_dir || -e $emacs_filename) && (!$html_dir || -e $html_cat_filename)) {
	next;
    }

    my $daystr = ("SO","MO","DI","MI","DO","FR","SA")[$wday];

    print "fetching " . scalar(localtime($daytime)) . " ($daystr)\n";

    if ($emacs_dir) {
	open(EMACS_OUTFILE, ">$emacs_filename") or die "cannot open $emacs_filename";
	print EMACS_OUTFILE ";;; -*- lisp -*-\n\n(\n";
    }
    if ($html_dir) {
	open(HTML_CAT_OUTFILE, ">$html_cat_filename") or die "cannot open $html_cat_filename";

	print HTML_CAT_OUTFILE "<head><title>TV program for $mday/$month</title></head>\n";
	print HTML_CAT_OUTFILE "<body BGCOLOR=WHITE>\n";
	print HTML_CAT_OUTFILE "<table>\n";

	foreach my $category (@categories)
	{
	    print HTML_CAT_OUTFILE "<tr><td><a href=\"#$category\">$catnames{$category}</a></td>\n";
	    print HTML_CAT_OUTFILE "    <td bgcolor=$catcolor{$category}>&nbsp;&nbsp;</td><tr>\n";
	}

	print HTML_CAT_OUTFILE "</table>\n";
	print HTML_CAT_OUTFILE "<br><br>";
	
	print HTML_CAT_OUTFILE "<table>\n";
    }

    foreach my $category (@categories) {
	my $begin = 0;
	my ($last_hour, $last_minute) = (0, 0);

	if ($html_dir) {
	    print HTML_CAT_OUTFILE "<tr><td colspan=4><a name=$category><h1>$catnames{$category}</h1></a></td></tr>\n";
	}

	print "  $category\n";

      LOOP: while (1) {
	  my $url = "http://www.tvtoday.de/tv/programm/programm.hbs?uhrzeit=Ax00&sender=alle&sparte=$category&tag=$daystr&action=suche&von=$begin";
	  my $num_found = 0;

	  print "    .\n";
	  #print "$url\n";

	  my $request = HTTP::Request->new(GET => $url);
	  my $response = $ua->request($request);

	  $response->is_success or die "request error";

	  my $content = $response->content;

	  $content =~ /\w+, (\d+)\.(\d+)\.(\d+)/ or die "could not find date in content";

	  $1 == $mday && $2 == $month + 1 && ($3 == $year || $3 == 1900 + $year) or die "date mismatch";

	  while ($content =~ /<dt>((.|\n)+?)(?=<dt>|<\/dl>)/g) {
	      my $str = $1;

	      if ($str =~ /<li><b>(\d+)\.(\d+) (.+?)<\/b> \((.+?)\)/g) {
		  my ($hour, $minute, $title, $station) = ($1, $2, $3, $4);
		  my $aux;
		  my $showview;
		  my $vps;
		  my $filmurl;

		  if ($title =~ /^<a href=\"(.+?)\">/) {
		      $filmurl = $1;
		      $title =~ s/<.+?>//g;
		  }

		  if ($str =~ /<dd>(.+)/) {
		      $aux = $1;

		      $aux =~ s/<br>/\n/gi;
		      $aux =~ s/[ \t]+/ /g;
		      $aux =~ s/^ //;
		      $aux =~ s/\n /\n/g;
		      $aux =~ s/\n+/\n/g;
		      $aux =~ s/\n$//;

		      if ($aux =~ /\((ShowView (\d+(-\d+)*))? ?(VPS (\d+(-\d+)*))?\)/) {
			  $showview = $2;
			  $vps = $5;

			  $aux =~ s/\s*\((ShowView (\d+(-\d+)*))? ?(VPS (\d+(-\d+)*))?\)\s*//;
		      }
		  }

		  if ($hour < $last_hour - 2) { # || ($hour == $last_hour && $minute < $last_minute)) {
		      #print "day limit\n";
		      last LOOP;
		  }

		  ($last_hour, $last_minute) = ($hour, $minute);

		  ++$num_found;

		  #print "|$category| $hour:$minute --- $title ($station) [$showview | $vps]\n";
		  if ($aux) {
		      #print "$aux\n\n";
		  }

		  if (grep /^\Q$station\E$/, @stations) {
		      if ($emacs_dir) {
			  print EMACS_OUTFILE "[", $year + 1900, " ", $month + 1, " ", $mday, " $category $hour $minute ",
			                      lisp($title), " ", lisp($filmurl), " ", lisp($station), " ", lisp($showview),
			                      " ", lisp($vps), " ", lisp($aux), "]\n";
		      }
		      if ($html_dir) {
			  $hour = sprintf("%02d", $hour);

			  print HTML_CAT_OUTFILE "<tr bgcolor=lightblue><td><b>$hour:$minute</b></td><td>$station</td><td><b>$title</b></td><td bgcolor=$catcolor{$category}>$category</td></tr>\n";
			  #print OUTFILE	"<tr><td colspan=2>&nbsp;</td>					<td>$aux</td><td>&nbsp;</td></tr>";
			  print HTML_CAT_OUTFILE "\n\n";

			  push @lines_time , 	"$hour;$minute;$station;$title;$category;$aux";
			  push @lines_overview, "$station;$hour;$minute;$title;$category";
		      }
		  } else {
		      #print "ditched\n";
		  }
	      } else {
		  print "no match\n";
		  print "$str\n\n";
	      }
	  }

	  if ($num_found > 0) {
	      $begin += 20;
	  } else {
	      #print "search limit\n";
	      last LOOP;
	  }
      }
    }

    if ($emacs_dir) {
	print EMACS_OUTFILE ")\n";
	close(EMACS_OUTFILE);
    }
    if ($html_dir) {
	print HTML_CAT_OUTFILE "</table>\n</body>";
	close(HTML_CAT_OUTFILE);
    }

    if ($html_dir) {
	### html-time

	my $filename = sprintf("%s/tv-%d-%02d-%02d-time.html", $html_dir, 1900 + $year, $month + 1, $mday);

	open(OUTFILE, ">$filename") or die "cannot open $filename";

	print OUTFILE	"<head><title>TV program for $mday/$month</title></head>\n";
	print OUTFILE	"<body BGCOLOR=WHITE>\n";
	print OUTFILE 	"<br><br>";
	print OUTFILE	"<table>\n";

	my @fields;

	foreach my $line (sort @lines_time) {
	    @fields = split /;/, $line;
	    #print "$fields[0]    $fields[1] $fields[2] $fields[3]\n";
	    print OUTFILE	"<tr bgcolor=lightblue><td><b>$fields[0]:$fields[1]</b></td>	<td>$fields[2]</td>	<td><b>$fields[3]</b></td><td bgcolor=$catcolor{$fields[4]}>$fields[4]</td></tr>\n";
	    #print OUTFILE "<tr><td colspan=2>&nbsp;</td>					<td>$fields[5]</td><td>&nbsp;</td></tr>";
	    print OUTFILE "\n\n";
	}
	
	print OUTFILE "</table>\n</body>";

	close(OUTFILE);

	### html-station

	my $filename = sprintf("%s/tv-%d-%02d-%02d-station.html", $html_dir, 1900 + $year, $month + 1, $mday);

	open(OUTFILE, ">$filename") or die "cannot open $filename";

	print OUTFILE	"<head><title>TV program for $mday/$month</title></head>\n";
	print OUTFILE	"<body BGCOLOR=WHITE>\n";
	print OUTFILE 	"<br><br>";

	foreach my $station (sort @stations)
	{
	    print OUTFILE "<a href=\"#$station\">$station</a><br>\n";
	}


	
	print OUTFILE	"<table>\n";

	my ($station, $hour, $min, $title, $category, $aux) = ("" , 0,0, "", "", "");

	my $first = 1;
	my $sender = "";

	foreach my $line (sort @lines_overview) {
	    ($station, $hour, $min, $title, $category, $aux) = split /;/, $line;

	    # new station?
	    if ($station ne $sender)
	    {
				print OUTFILE "<tr><td colspan=3><br><h1><a name=$station>$station<a></h1></td></tr>\n";
		}
		
		$first 	= 0;
		$sender = $station;

	    print OUTFILE	"<tr bgcolor=lightblue><td><b>$hour:$min</b></td><td>$title<td><td bgcolor=$catcolor{$category}>$category</td></tr>\n";
	}
	
	print OUTFILE "</table>\n</body>";

	close(OUTFILE);


	### html-overview

	my $top_basename = sprintf("tv-%d-%02d-%02d-overview.html", 1900 + $year, $month + 1, $mday);
	my $stations_basename = sprintf("stations-%d-%02d-%02d-overview.html", 1900 + $year, $month + 1, $mday);
	my $data_basename = sprintf("data-%d-%02d-%02d-overview.html", 1900 + $year, $month + 1, $mday);

	open(TOP_OUTFILE, ">$html_dir/$top_basename") or die "cannot open $html_dir/$filename";
	print TOP_OUTFILE "<html><head><title>TV program for $mday/$month</title></head>\n";
	print TOP_OUTFILE "<frameset cols=\"130,*\" border=\"0\">\n";
	print TOP_OUTFILE "<frame src=\"$stations_basename\">\n";
	print TOP_OUTFILE "<frame src=\"$data_basename\">\n";
	print TOP_OUTFILE "</frameset>\n";
	print TOP_OUTFILE "</html>\n";
	close TOP_OUTFILE;

	open(STATIONS_OUTFILE, ">$html_dir/$stations_basename") or die "cannot open $html_dir/$stations_basename";
	open(DATA_OUTFILE, ">$html_dir/$data_basename") or die "cannot open $html_dir/$data_basename";

	print STATIONS_OUTFILE "<html><body bgcolor=white cols=289>\n<table>\n";
	print DATA_OUTFILE "<html><body bgcolor=white cols=289>\n<table>\n";

	@lines_overview = sort @lines_overview;
	$first			= 1;

	foreach my $line (@lines_overview) {
	    my ($ostation, $ohour, $omin, $otitle, $ocategory, $oaux) = ($station, $hour, $min, $title, $category, $aux);

	    ($station, $hour, $min, $title, $category, $aux) = split /;/, $line;
	    $min = sprintf("%02d", int($min/5)*5);

	    # new station?
	    if ($station ne $sender)
	    {
		if  ($first == 0)
		{
		    print DATA_OUTFILE movie_table_data($ohour, $omin,
							24, 0,
							$otitle, $ocategory);
		    print STATIONS_OUTFILE "</tr>\n";
		    print DATA_OUTFILE "</tr>\n";
		}

		$first = 0;
		
		print STATIONS_OUTFILE "<tr><td nowrap bgcolor=lightblue>$station</td>\n";
		print DATA_OUTFILE "<tr>\n";

		$sender = $station;

		($ostation, $ohour, $omin, $otitle, $ocategory, $oaux) = ("" , 0, 0, "", "", "");
	    }

	    print DATA_OUTFILE movie_table_data($ohour, $omin, 
						$hour, $min,
						$otitle, $ocategory);
	}

	print DATA_OUTFILE movie_table_data($hour, $min,
					    24, 0,
					    $title, $category);
	print STATIONS_OUTFILE "</tr>\n</table>\n</body></html>";
	print DATA_OUTFILE "</tr>\n</table>\n</body></html>";

	close(DATA_OUTFILE);
	close(STATIONS_OUTFILE);
    }
}

if ($html_dir) {
    open(OUTFILE, ">$html_dir/index.html") or die "cannot open $html_dir/index.html";

    print OUTFILE "<head><title>TV program overview</title></head>\n";
    print OUTFILE "<body BGCOLOR=WHITE>\n";

    foreach my $file (sort glob("$html_dir/tv-*.html")) {
	$file =~ /([^\/]+)$/;

	my $basename = $1;

	print OUTFILE "<a href=\"$basename\">$basename</a><br>\n";
    }

    print OUTFILE "</body>";
    close(OUTFILE);
}
