Hi,
   I have a working xmltv setup here. It required some hacking into the
downloader code for Israel. First of all, you should use tvtime which has
xmltv support. Second, you need the tv_grab_il script attached. Third,
you'll need a cron job something like this (here I download twice per week):

20 6 * * 0,3 cp /home/alon/media/TV/listings.xml 
/home/alon/media/TV/listings.xml.old && /usr/local/bin/tv_grab_il | tv_sort > 
/home/alon/media/TV/listings.xml

Fourth, you need to configure tvtime to use your XMLTV file and correctly
modify the ~/.tvtime/stationlist.xml file with XMLTV ids (I'm attaching my
file).

Good luck!

On Mon, 5 Feb 2007, Amichai Rotman wrote:

> Hi all,
> 
> I would like to set up Freevo on my Ubuntu 6.10 box and make use of the TV
> guide feature. I understand it uses XMLTV to get the TV guide (like the EPG
> on digital broadcast) but I don't know how to set it up.
> 
> I tried to follow the instructions but it is very unfriendly and confusing.
> 
> Any of you know of an existing guide / HOWTO or did it him/her self?
> 
> Thanks!
> 
>

-- 
This message was sent by Alon Altman ([EMAIL PROTECTED]) ICQ:1366540
GPG public key at http://8ln.org/pubkey.txt
Key fingerprint = A670 6C81 19D3 3773 3627  DE14 B44A 50A3 FE06 7F24
--------------------------------------------------------------------------
  -=[ Random Fortune ]=-
Any philosophy that can be put "in a nutshell" belongs there.
                -- Sydney J. Harris

-- Attached file included as plaintext by Listar --
-- File: tv_grab_il

#!/usr/bin/perl -w

=pod

=head1 NAME

tv_grab_il - Grab TV listings for Israel.

=head1 SYNOPSIS

tv_grab_il --help

tv_grab_il [--config-file FILE] --configure

tv_grab_il [--config-file FILE] [--output FILE] [--days N]
           [--offset N] [--quiet]

=head1 DESCRIPTION

Outputs TV listings for channels available in Israel (free to air, cable
and satellite). The data is obtained from parsing web pages from the Israeli
portal walla (from tv.walla.co.il).

First run B<tv_grab_il --configure> to decide which channels to download. There
is a long list. You may want to select none when it asks you for which
channels and manually edit the configuration file to uncomment the channels
you wish to tape. Then run B<tv_grab_il> with no arguments to output the
listing in XML format to the standard output.

To view the hebrew, you will need to set your terminal to have a unicode font
that supports hebrew.

B<--configure> Prompt for which channels, and write the configuration file.
B<--config-file FILE> Set the name of the configuration file, the
default is B<~/.xmltv/tv_grab_il.conf>.  This is the file written by
B<--configure> and read when grabbing.

B<--output FILE> write to FILE rather than standard output.

B<--days N> grab N days.  The default is 7 (there does not seem to be more
information than this anyway on the server in general).

B<--offset N> start N days in the future.  The default is to start
from today.

B<--quiet> suppress the progress messages normally written to standard
error.

=head1 SEE ALSO

L<xmltv(5)>.

=head1 AUTHOR

Written by Jason Friedman, [EMAIL PROTECTED] This program is
based on tv_grab_sn, written by Stefan G:orling, [EMAIL PROTECTED] and
maintained by Staffan Malmgren, [EMAIL PROTECTED]

Patched by Alon Altman.

Last updated: 5 February, 2007.

=head1 BUGS

The summer time routine uses the European summer time start and stop
dates which are different to those used in Israel. The correct times
can be found at
http://www.greenwichmeantime.com/local/asia/il.htm?israel+jerusalem+tel_aviv

=cut

use strict;
#binmode(STDOUT,":utf8");
#binmode(STDERR,":utf8");
use HTML::TreeBuilder;
use Date::Manip;
use Getopt::Long;
use Locale::Hebrew;
use Encode;
use XMLTV;
use XMLTV::Memoize;
use XMLTV::Ask;
use XMLTV::TZ qw(parse_local_date);
use XMLTV::DST qw(utc_offset);
use XMLTV::Config_file;
use XMLTV::Get_nice;
use XMLTV::Mode;
use XMLTV::Usage <<END
$0: get Israeli television listings in XMLTV format
To configure: $0 --configure [--config-file FILE]
To grab listings: $0 [--config-file FILE] [--output FILE] [--days N]
        [--offset N] [--quiet]
END
  ;

# Use Term::ProgressBar if installed.
use constant Have_bar => eval { require Term::ProgressBar; 1 };

# Memoize some date parsing routines, if possible.  FIXME move to
# XMLTV::Memoize.
#
eval { require Memoize };
unless ($@) {
  foreach (qw(utc_offset ParseDate UnixDate dc fetch_data)) {
    Memoize::memoize($_) or warn "cannot memoize $_";
  }
}

sub xhead();
sub configure();
sub get_channels();
sub fetch_data ($$);
sub get_display_name ($);
sub process_file( $$$$$ );
sub read_config_file( $ );
sub dc ( $$ );
sub reencode ( $ );


# The base timezone ("winter time") and "summer time" for Israel is 
# equivalent however the switchover dates are different (see BUGS)
my $BASE_TZ = "EET";
my $PAGE_ENCODING = "Windows-1255";
my $DOMAIN = 'tv.walla.co.il';

XMLTV::Memoize::check_argv('XMLTV::Get_nice::get_nice_aux');
my ($opt_days, $opt_help, $opt_output,
    $opt_offset,$opt_configure, $opt_config_file, $opt_quiet);
$XMLTV::Get_nice::Delay=1;
$opt_days  = 7; # default
$opt_quiet  = 0; # default
$opt_offset = 0; #default
GetOptions('days=i'        => \$opt_days,
           'offset=i'      => \$opt_offset,
           'help'          => \$opt_help,
           'configure'     => \$opt_configure,
           'config-file=s' => \$opt_config_file,
           'output=s'      => \$opt_output,
           'quiet'         => \$opt_quiet
          )
  or usage(0);
die 'number of days must not be negative'
  if (defined $opt_days && $opt_days < 0);
usage(1) if $opt_help;

my $mode = XMLTV::Mode::mode('grab', # default
                             $opt_configure => 'configure',
                            );
# MAIN ROUTINE

my $now = dc(parse_local_date('now'),"$opt_offset days");
$now = substr($now,0,8);

# Find the config file
my $config_file = 
  XMLTV::Config_file::filename($opt_config_file, 'tv_grab_il', $opt_quiet);

if ($mode eq 'configure') {
  configure();
  exit();
}

my %w_args;

if (defined $opt_output) {
  my $fh = new IO::File(">$opt_output");
  $w_args{OUTPUT} = $fh;
}
$w_args{encoding} = 'utf-8';


# GRABBING DATA:

my (%channels,$channel,@dates,$date,$i);
%channels = read_config_file($config_file);

my $writer = new XMLTV::Writer(%w_args);

$writer->start(xhead);

my @to_get;

my $bar = new Term::ProgressBar('getting channel info', scalar keys %channels)
  if Have_bar && not $opt_quiet;
foreach my $channel (keys %channels) {
    my $ch_xid = "$channel.$DOMAIN";
    # fetch today's data to get the channel name
    # (Hopefully memoize should prevent the data being fetched twice)
    my $data = fetch_data(UnixDate($now,'%Y-%m-%d'),$channel);
    my $display_name = ($channel == 14 ? 'national geographic' : 
get_display_name($data));
    $writer->write_channel({ id => $ch_xid,
                             'display-name' => [[ 
reencode($display_name),"he_IL.UTF8" ]] });
    update $bar if Have_bar && not $opt_quiet;
}
my $day = $now;
for (my $i = 0 ;$i < $opt_days; $i++) {
    if ($i > 0 ) {
        $day = dc($day, '+ 1 day');
    }
    push @to_get, [ UnixDate($day,'%Y-%m-%d'), "$_.$DOMAIN", $_ , ($i==0)]
    #push @to_get, [ $day, "$_.$DOMAIN", $_ , ($i==0)]
      foreach keys %channels;
}

my $today = UnixDate($now, '%Y-%m-%d');

$bar = new Term::ProgressBar('getting listings', scalar @to_get)
  if Have_bar && not $opt_quiet;

foreach (@to_get) {
  my ($day, $ch_xid, $ch_did,$isfirstday) = @$_;
  my $data = fetch_data($day,$ch_did);
  process_file($writer,$data,$day,$ch_xid,$isfirstday);

  update $bar if Have_bar && not $opt_quiet;
}

$writer->end();
exit();
#######################################################################
sub get_display_name ( $ ) {
  my($data) = @_;

  my $tree = HTML::TreeBuilder->new_from_content($data);
  my @first_list = $tree->look_down(
                                    '_tag','td',
                                    sub {
                                      (defined($_[0]->attr('class')) && 
$_[0]->attr('class') =~ /^w5b$/)
                                    } );
  die "Cannot find channel name" if (scalar(@first_list)==0);
  my $channel_name = $first_list[0]->as_text;
  $channel_name =~ s/ *[^ ]* *//;
  $channel_name =~ s/^ *//;
  $channel_name =~ s/ *$//;
  $channel_name = Locale::Hebrew::hebrewflip($channel_name);
  return $channel_name;
}

#######################################################################
sub process_file( $$$$$ ) {
  my($writer,$data,$date,$channel) = @_;

  my @genrenames = 
("family","movie","music","sport","news","latenight","youth");

#  print "$data\n";
  my $tree = HTML::TreeBuilder->new_from_content($data);

  my @show_details = $tree->look_down(
                                    '_tag','a',
                                      sub {
                                        $_[0]->attr('href') =~ 
/\?w=\/[0-9]+\/[0-9]+\/[0-9]{4}-[0-9][0-9]-[0-9][0-9]\/1$/
                                      }
                                     );
  my $detail;
  my (@starttimes, @endtimes, @prognames, @genres);
  foreach $detail (@show_details) {
    my $progname =  $detail->as_text;
    my $starttime = 
$detail->parent->parent->content->[4]->content->[0]->as_text;
    my $genre_string = 
$detail->parent->parent->content->[3]->content->[0]->attr('src');
    $genre_string =~ /genre\/(.*)\.gif/;
    push @starttimes, $starttime;
#    push @prognames, reencode(Locale::Hebrew::hebrewflip($progname));
    push @prognames, reencode($progname);
   push @genres, $genrenames[$1-1];
  }

  if (not @starttimes) {
    warn "nothing found for date $date, channel $channel\n";
    return;
  }

  my ($i);
  my $prevhour=0;
  for $i (1 ... scalar @starttimes) {
    my $time=$starttimes[$i-1];
    $time =~ /(\d+):\d+/o;
    my $hour= $1;
    if ($hour<$prevhour) {
      $date = UnixDate(dc($date, '+ 1 day'), '%Y-%m-%d');
    }
    $prevhour=$hour;
    my (%program);
    $program{title} = [[$prognames[$i-1],"he_IL.UTF8"]];
    $program{start} = utc_offset("$date $starttimes[$i-1]",$BASE_TZ);
    $program{channel} = $channel;
    $program{category}  = [[$genres[$i-1], "en"]];
    $writer->write_programme(\%program);
  }
}

#######################################################################
# fetch the web page
# Parameters:
#    date
#    channel number (on web page)
#    directory for caching data

sub fetch_data ( $$ ) {
  my($date,$channel) = @_;

  my $data;
  my $url = "http://$DOMAIN/?w=/$channel//$date/1";;

  my $shortdate = $date;
  $shortdate =~ s/-//g;

  $data = get_nice($url);

  if (not defined $data) {
    die "Could not download web page $url. Check internet settings\n";
  }
  return $data;
}

##############################################################################
sub read_config_file( $ ) {
  my ($config_file) = @_;
  my (@config_lines,%channels,$ch_did);#,$ch_name);

  @config_lines = XMLTV::Config_file::read_lines($config_file);
  foreach (@config_lines) {
    # get rid of comments, space
    next if not defined;

     if (/^channel:?\s+(\d+)/) {
        $ch_did = $1;
        $channels{$ch_did} = 1;
      } 
     elsif (/^$/) {; # ignore empty lines
                 }
     else {
       warn "$config_file:$.: bad line\n";
     }
   }
  die "No channels specified, run me with --configure\n"
    if not %channels;

  return %channels;
}

##############################################################################

# Wrapper for DateCalc().
sub dc( $$ ) {
  my $err;
  my $r = DateCalc(@_, \$err);
  die "DateCalc() failed with $err" if $err;
  die 'DateCalc() returned undef' if not defined $r;
  return $r;
}

##############################################################################

sub xhead() {
  return { 'source-info-url'     => "http://$DOMAIN/";,
           'source-data-url'     => "http://$DOMAIN";,
           'generator-info-name' => 'XMLTV',
           'generator-info-url'  => 'http://membled.com/work/apps/xmltv/',
         };
}

#############################################################################

sub configure() {
  XMLTV::Config_file::check_no_overwrite($config_file);

  # FIXME commonize this configuration stuff within the XMLTV project.
  open(CONF, ">$config_file") or die "cannot write to $config_file: $!";
  my $bar = new Term::ProgressBar('getting channel list', 1)
    if Have_bar && not $opt_quiet;
  my ($chsptr) = get_channels();
  update $bar if Have_bar && not $opt_quiet;

  my @chs = @$chsptr;

  my @names = map {$_->{'display-name'}->[0]->[0] } @chs; #filteredchs;
  my @qs = map { "add channel $_?" } @names;
  my @want = ask_many_boolean(1, @qs);

  foreach (@chs) {
        my $w = shift @want;
        warn("cannot read input, stopping channel questions"), last
          if not defined $w;
        # No need to print to user - XMLTV::Ask is verbose enough.

        # Print a config line, but comment it out if channel not wanted.
        print CONF '#' if not $w;
        my $name = shift @names;
        print CONF "channel $_->{id}\n";
    }

    close CONF or warn "cannot close $config_file: $!";
    say "All done, run with no arguments to grab listings.\n";
}

############################################################################
# get the channels for Israel and their categories
sub get_channels() {

my ($channelspage,$location,@r);

$location = "http://$DOMAIN/?w=/4";;
$channelspage = get_nice($location);
if (not defined $channelspage) {
  die "cannot get $channelspage";
}

my $tree = HTML::TreeBuilder->new_from_content($channelspage);

my @channel_list = $tree->look_down(
                                     '_tag','a',
                                     sub {
                                       $_[0]->attr('href') =~ 
/\?w=\/[0-9]*\/\/[0-9]{4}-[0-9][0-9]-[0-9][0-9]\/1$/
                                     }
                                    );

my 
($current_table,$channel_name,$channel_number,$channel_element,$channel_content,$channel_type);

my (%types,%contents);

foreach $channel_element (@channel_list) {
  # ignore links to images
  if (defined($channel_element->look_down('_tag','img'))) { next; };
  $channel_content = $channel_element->as_text;
  $channel_name = $channel_element->as_text;
  $channel_element->starttag() =~ /w=\/([0-9]*)/;
  $channel_number = $1;

  push @r, {'display-name' => [[ $channel_name, "he_IL.UTF8"]], 'id' => 
$channel_number };
}

# Now that we're done with it, we must destroy it.
$tree = $tree->delete;
return ([EMAIL PROTECTED]);
}

############################################################################
# reencode a string
sub reencode( $ ) {
  my ($thestring) = @_;
  return (encode_utf8(decode($PAGE_ENCODING,$thestring)));
}

-- Binary/unsupported file stripped by Listar --
-- Type: APPLICATION/xml
-- File: stationlist.xml


=================================================================
To unsubscribe, send mail to [EMAIL PROTECTED] with
the word "unsubscribe" in the message body, e.g., run the command
echo unsubscribe | mail [EMAIL PROTECTED]

Reply via email to