#!/usr/bin/perl -w eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' if 0; # not running under some shell =pod =head1 NAME tv_augment - Augment XMLTV listings files with automatic and user-defined rules. =head1 SYNOPSIS tv_augment [--rule ] [--config ] [--input ] [--output ] [--log ] [--nostats] [--debug ] tv_augment [-r ] [-c ] [-i ] [-o ] [-l ] [-n] [-d ] =head1 DESCRIPTION Augment an XMLTV xml file by applying corrections ("fixups") to programmes matching defined criteria ("rules"). Two types of rules are actioned: (i) automatic, (ii) user-defined. Automatic rules use pre-programmed input and output to modify the input programmes. E.g. removing a "title" where it is repeated in a "sub-title" (e.g. "Horizon" / "Horizon: Star Wars"), or trying to identify and extract series/episode numbers from the programme title, sub-title or description. User-defined rules use the content of a "rules" file which allows programmes matching certain user-defined criteria to be corrected/enhanced with the user data supplied (e.g. adding/changing categories for all episodes of "Horizon", or fixing misspellings in titles, etc.) (see "perldoc XMLTV::Augment" for more details) B<--input FILE> read from FILE rather than standard input. B<--output FILE> write to FILE rather than standard output. B<--rule FILE> file containing the user-defined rules. B<--config FILE> configuration file containing a list of which rules you want to run. B<--nostats> do not print the summary log of actions performed, or list of suggested fixups. B<--log FILE> output the stats to this FILE. B<--debug LEVEL> print debug info to STDERR (debug level > 3 is not likely to be of much use (it generates a lot of output)) =head1 SEE ALSO L =head1 AUTHOR Geoff Westcott, honir.at.gmail.dot.com, Dec. 2014. =cut use strict; use XMLTV; use XMLTV::Version "$XMLTV::VERSION"; use Data::Dumper; use Getopt::Long; use XMLTV::Data::Recursive::Encode; # simplify testing by also looking for package in current directory eval 'use XMLTV::Augment'; if ($@ ne '') { eval 'use Augment'; } use XMLTV::Usage <] [--config ] [--input ] [--output ] [--nostats] [--log ] [--debug (1-10)] $0 [-r ] [-c ] [-i ] [-o ] [-n] [-l ] [-d (1-10)] END ; my ( $opt_help, $opt_input, $opt_output, $opt_rule, $opt_config, $opt_nostats, $opt_log, $opt_debug, $opt_do, ); GetOptions( 'h|help' => \$opt_help, 'i|input=s' => \$opt_input, 'o|output=s' => \$opt_output, 'r|rule=s' => \$opt_rule, 'c|config|config-file=s' => \$opt_config, 'n|nostats' => \$opt_nostats, 'l|log:s' => \$opt_log, 'd|debug:i' => \$opt_debug, 'do:i' => \$opt_do, ) or usage(0); usage(1) if $opt_help; #rule is now optional if using Supplement via config # usage(0) if !$opt_rule; $opt_input = '-' if ( !defined($opt_input) ); #$opt_output = 'STDOUT' if ( !defined($opt_output) ); $opt_debug = 0 if ( !defined($opt_debug) ); my $opt_stats = ( !defined($opt_nostats) ? 1 : !$opt_nostats ); # object construction & open log file my $augment = new XMLTV::Augment( 'rule' => $opt_rule, 'config' => $opt_config, 'debug' => $opt_debug, 'stats' => $opt_stats, 'log' => $opt_log, ) || eval { print STDERR "Failed to create XMLTV::Augment object \n"; exit 1; }; my %w_args = (); if (defined $opt_output) { my $fh = new IO::File ">$opt_output"; die "cannot write to $opt_output\n" if not $fh; %w_args = (OUTPUT => $fh); } # our XMLTV::Writer object my $w; # store the input file's encoding my $encoding; # count of input records my $in_count = 0; # parsefiles_callback needs an array my @files = ( $opt_input ); XMLTV::parsefiles_callback(\&encoding_cb, \&credits_cb, \&channel_cb, \&programme_cb, @files); # note: we only get a Writer if the encoding callback gets called if ( $w ) { $w->end(); } # log the stats $augment->printInfo(); # close the log file $augment->end(); exit(0); # callbacks used by parsefiles_callback # sub encoding_cb( $ ) { die if defined $w; $encoding = shift; # callback returns the file's encoding $w = new XMLTV::Writer(%w_args, encoding => $encoding); $augment->setEncoding($encoding); } # sub credits_cb( $ ) { $w->start(shift); } # sub channel_cb( $ ) { my $ch = shift; # store the channel details $augment->inputChannel( $ch ); # write the channel element to the output xml $w->write_channel($ch); } # sub programme_cb( $ ) { my $prog = shift; $in_count++; # developer's option to only process a few records in input file and then stop if ( defined($opt_do) && $in_count > $opt_do ) { return; } # decode the incoming programme $prog = XMLTV::Data::Recursive::Encode->decode($encoding, $prog); # augmentProgramme will now do any requested processing of the input xml $prog = $augment->augmentProgramme( $prog ); # re-code the modified programme back to original encoding $prog = XMLTV::Data::Recursive::Encode->encode($encoding, $prog); # output the augmented programme $w->write_programme($prog); } #