.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.40) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Augment 3pm" .TH Augment 3pm "2021-02-09" "perl v5.32.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" XMLTV::Augment \- Augment XMLTV listings files with automatic and user\-defined rules. .SH "DESCRIPTION" .IX Header "DESCRIPTION" Augment an \s-1XMLTV\s0 xml file by applying corrections (\*(L"fixups\*(R") to programmes matching defined criteria (\*(L"rules\*(R"). .PP Two types of rules are actioned: (i) automatic, (ii) user-defined. .PP Automatic rules use pre-programmed input and output to modify the input programmes. E.g. removing a \*(L"title\*(R" where it is repeated in a \*(L"sub-title\*(R" (e.g. \*(L"Horizon\*(R" / \*(L"Horizon: Star Wars\*(R"), or trying to identify and extract series/episode numbers from the programme"s title, sub-title or description. .PP User-defined rules use the content of a \*(L"rules\*(R" 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 \*(L"Horizon\*(R", or fixing misspellings in titles, etc.) .PP By setting appropriate options in the \*(L"config\*(R" file, the \*(L"rules\*(R" file can be automatically downloaded using XMLTV::Supplement. .SH "EXPORTED FUNCTIONS" .IX Header "EXPORTED FUNCTIONS" .IP "\fB\fBsetEncoding\fB\fR" 4 .IX Item "setEncoding" Set the assumed encoding of the rules file. .IP "\fB\fBinputChannel\fB\fR" 4 .IX Item "inputChannel" Store each channel found in the input programmes file for later processing by \*(L"stats\*(R". .IP "\fB\fBaugmentProgramme\fB\fR" 4 .IX Item "augmentProgramme" Augment a programme using (i) pre-determined rules and (ii) user-defined rules. Which rules are processed is determined by the options set in the \*(L"config\*(R" file. .IP "\fB\fBprintInfo\fB\fR" 4 .IX Item "printInfo" Print the lists of actions taken and suggestions for further fixups. .IP "\fB\fBend\fB\fR" 4 .IX Item "end" Do any final processing before exit (e.g. close the log file if necessary). .SH "INSTANTIATION" .IX Header "INSTANTIATION" .Vb 1 \& new XMLTV::Augment( { ...parameters...} ); .Ve .PP Possible parameters: rule => filename of file containing fixup rules (if omitted then no user-defined rules will be actioned) (overrides auto-fetch Supplement if that is defined; see sample options file) config => filename of config file to read (if omitted then no config file will be used) encoding => assumed encoding of the rules file (default = \s-1UTF\-8\s0) stats => whether to print the audit stats in the log (values = 0,1) (default = 1) log => filename of output log debug => debug level (values 0\-10) (default = no debug) note debug level > 3 is not likely to be of much use unless you are developing code .SH "TYPICAL USAGE" .IX Header "TYPICAL USAGE" .Vb 4 \& 1) Create the XMLTV::Augment object \& 2) Pass each channel to inputChannel() \& 3) Pass each programme to augmentProgramme() \& 4) Tidy up using printInfo() & end() \& \& #instantiate the object \& my $augment = new XMLTV::Augment( \& "rule" => "myrules.txt", \& "config" => "myconfig.txt", \& "log" => "augment.log", \& ); \& die "failed to create XMLTV::Augment object" if !$augment; \& \& for each channel... { \& # store the channel details \& $augment\->inputChannel( $ch ); \& } \& \& for each programme... { \& # augmentProgramme will now do any requested processing of the input xml \& $prog = $augment\->augmentProgramme( $prog ); \& } \& \& # log the stats \& $augment\->printInfo(); \& \& # close the log file if necessary \& $augment\->end(); .Ve .PP Note: you are responsible for reading/writing to the \s-1XMLTV\s0 .xml file; the package will not do that for you. .SH "RULES" .IX Header "RULES" .IP "\fBremove_duplicated_new_title_in_ep\fR" 4 .IX Item "remove_duplicated_new_title_in_ep" Rule #A1 .Sp Remove \*(L"New \f(CW$title\fR :\*(R" from .Sp .Vb 2 \& If sub\-title starts with "New" + + separator, then it will be removed from the sub\-title \& "separator" can be any of .,:;\- \& \& in : "Antiques Roadshow / New Antiques Roadshow: Doncaster" \& out: "Antiques Roadshow / Doncaster" .Ve .IP "\fBremove_duplicated_title_and_ep_in_ep\fR" 4 .IX Item "remove_duplicated_title_and_ep_in_ep" Rule #A2 .Sp Remove duplicated programme title *and* episode from <sub\-title> .Sp .Vb 2 \& If sub\-title starts with <title> + separator + <episode> + separator + <episode>, then it will be removed from the sub\-title \& "separator" can be any of .,:;\- \& \& in : "Antiques Roadshow / Antiques Roadshow: Doncaster: Doncaster" \& out: "Antiques Roadshow / Doncaster" .Ve .IP "\fBremove_duplicated_title_in_ep\fR" 4 .IX Item "remove_duplicated_title_in_ep" Rule #A3 .Sp Remove duplicated programme title from <sub\-title> .Sp .Vb 5 \& i) If sub\-title starts with <title> + separator, then it will be removed from the sub\-title \& ii) If sub\-title ends with separator + <title>, then it will be removed from the sub\-title \& iii) If sub\-title starts with <title>(...), then the sub\-title will be set to the text in brackets \& iv) If sub\-title equals <title>, then the sub\-title will be removed \& "separator" can be any of .,:;\- \& \& in : "Antiques Roadshow / Antiques Roadshow: Doncaster" \& out: "Antiques Roadshow / Doncaster" \& \& in : "Antiques Roadshow / Antiques Roadshow (Doncaster)" \& out: "Antiques Roadshow / Doncaster" \& \& in : "Antiques Roadshow / Antiques Roadshow" \& out: "Antiques Roadshow / " .Ve .IP "\fBupdate_premiere_repeat_flags_from_desc\fR" 4 .IX Item "update_premiere_repeat_flags_from_desc" Rule #A4 .Sp Set the <premiere> element and remove any <previously\-shown> element if <desc> starts with \*(L"Premiere.\*(R" or \*(L"New series\*(R". Remove the \*(L"Premiere.\*(R" text. Set the <previously\-shown> element and remove any <premiere> element if <desc> starts with \*(L"Another chance\*(R" or \*(L"Rerun\*(R" or \*(L"Repeat\*(R" .IP "\fBcheck_potential_numbering_in_text\fR" 4 .IX Item "check_potential_numbering_in_text" Rule #A5 .Sp Check for potential series, episode and part numbering in the title, episode and description fields. .IP "\fBextract_numbering_from_title\fR" 4 .IX Item "extract_numbering_from_title" Rule #A5.1 .Sp Extract series/episode numbering found in <title>. .IP "\fBextract_numbering_from_episode\fR" 4 .IX Item "extract_numbering_from_episode" Rule #A5.2 .Sp Extract series/episode numbering found in <sub\-title>. .IP "\fBextract_numbering_from_desc\fR" 4 .IX Item "extract_numbering_from_desc" Rule #A5.3 .Sp Extract series/episode numbering found in <desc>. .IP "\fBmake_episode_from_part_numbers\fR" 4 .IX Item "make_episode_from_part_numbers" Rule #A5.4 .Sp If no <sub\-title> then make one from \*(L"part\*(R" numbers. .Sp .Vb 2 \& in : "Panorama / " desc = "Part 1/2..." \& out: "Panorama / Part 1 of 2" .Ve .IP "\fBprocess_user_rules\fR" 4 .IX Item "process_user_rules" Rule #user .Sp Process programme against user-defined fixups .Sp The individual rules each have their own option to run or not; consider this like an on/off switch for all of them. I.e. if this option is off then no user rules will be run (irrespective of any other option flags). .IP "\fBprocess_non_title_info\fR" 4 .IX Item "process_non_title_info" Rule #1 .Sp Remove specified non-title text from <title>. .Sp .Vb 2 \& If title starts with text + separator, then it will be removed from the title \& "separator" can be any of :;\- \& \& rule: 1|Python Night \& in : "Python Night: Monty Python \- Live at the Hollywood Bowl / " \& out: "Monty Python \- Live at the Hollywood Bowl / " .Ve .IP "\fBprocess_demoted_titles\fR" 4 .IX Item "process_demoted_titles" Rule #11 .Sp Promote demoted title from <sub\-title> to <title>. .Sp .Vb 2 \& If title matches, and sub\-title starts with text then remove matching text from sub\-title and move it into the title. \& Any text after \*(Aqseparator\*(Aq in the sub\-title is preserved. \*(Aqseparator\*(Aq can be any of .,:;\- \& \& rule: 11|Blackadder~Blackadder II \& in : "Blackadder / Blackadder II: Potato" \& out: "Blackadder II / Potato" .Ve .IP "\fBprocess_replacement_titles_desc\fR" 4 .IX Item "process_replacement_titles_desc" Rule #10 .Sp Replace specified <title> / <sub\-title> with title/episode pair supplied using <desc>. .Sp .Vb 1 \& If title & sub\-title match supplied data, then replace <title> and <sub\-title> with new data supplied. \& \& rule: 10|Which Doctor~~Gunsmoke~Which Doctor~Festus and Doc go fishing, but are captured by a family that is feuding with the Haggens. \& in : "Which Doctor / " desc> = " Festus and Doc go fishing, but are captured by a family that is feuding with the Haggens. ..." \& out: "Gunsmoke / Which Doctor" .Ve .IP "\fBprocess_replacement_titles_episodes\fR" 4 .IX Item "process_replacement_titles_episodes" Rule #8 .Sp Replace specified <title> / <sub\-title> with title/episode pair supplied. .Sp .Vb 1 \& If title & sub\-title match supplied data, then replace <title> and <sub\-title> with new data supplied. \& \& rule: 8|Top Gear USA Special~Detroit~Top Gear~USA Special \& in : "Top Gear USA Special / Detroit" \& out: "Top Gear / USA Special" \& \& rule: 8|Top Gear USA Special~~Top Gear~USA Special \& in : "Top Gear USA Special / " \& out: "Top Gear / USA Special" \& or \& in : "Top Gear USA Special / 1/6." \& out: "Top Gear / 1/6. USA Special" .Ve .IP "\fBprocess_mixed_title_subtitle\fR" 4 .IX Item "process_mixed_title_subtitle" Rule #2 .Sp Extract sub-title from <title>. .Sp .Vb 2 \& If title starts with text + separator, then the text after it will be moved into the sub\-title \& "separator" can be any of :;\- \& \& rule: 2|Blackadder II \& in : "Blackadder II: Potato / " \& out: "Blackadder II / Potato" .Ve .IP "\fBprocess_mixed_subtitle_title\fR" 4 .IX Item "process_mixed_subtitle_title" Rule #3 .Sp Extract sub-title from <title>. .Sp .Vb 2 \& If title ends with separator + text, then the text before it will be moved into the sub\-title \& "separator" can be any of :;\- \& \& rule: 3|Storyville \& in : "Kings of Pastry :Storyville / " \& out: "Storyville / Kings of Pastry" .Ve .IP "\fBprocess_reversed_title_subtitle\fR" 4 .IX Item "process_reversed_title_subtitle" Rule #4 .Sp Reverse <title> and <sub\-title> .Sp .Vb 1 \& If sub\-title matches the rule\*(Aqs text, then swap the title and sub\-title \& \& rule: 4|Storyville \& in : "Kings of Pastry / Storyville" \& out: "Storyville / Kings of Pastry" .Ve .IP "\fBprocess_replacement_titles\fR" 4 .IX Item "process_replacement_titles" Rule #5 .Sp Replace <title> with supplied text. .Sp .Vb 1 \& If title matches the rule\*(Aqs text, then use the replacement text supplied \& \& rule: 5|A Time Team Special~Time Team \& in : "A Time Team Special / Doncaster" \& out: "Time Team / Doncaster" .Ve .Sp This is the one which you will probably use most. It can be used to fix most incorrect titles \- e.g. spelling mistakes; punctuation; character case; etc. .IP "\fBprocess_subtitle_remove_text\fR" 4 .IX Item "process_subtitle_remove_text" Rule #13 .Sp Remove specified text from <sub\-title> for a given <title>. .Sp .Vb 3 \& If sub\-title starts with text + separator, or ends with separator + text, \& then it will be removed from the sub\-title. \& "separator" can be any of .,:;\- and is optional. \& \& rule: 13|Time Team~A Time Team Special \& in : "Time Team / Doncaster : A Time Team Special " \& out: "Time Team / Doncaster" .Ve .IP "\fBprocess_replacement_episodes\fR" 4 .IX Item "process_replacement_episodes" Rule #7 .Sp Replace <sub\-title> with supplied text. .Sp .Vb 1 \& If sub\-title matches the rule\*(Aqs text, then use the replacement text supplied \& \& rule: 7|Time Team~Time Team Special: Doncaster~Doncaster \& in : "Time Team / Time Team Special: Doncaster" \& out: "Time Team / Doncaster" .Ve .IP "\fBprocess_replacement_ep_from_desc\fR" 4 .IX Item "process_replacement_ep_from_desc" Rule #9 .Sp Replace <sub\-title> with supplied text when the <desc> matches that given. .Sp .Vb 1 \& If sub\-title matches the rule\*(Aqs text, then use the replacement text supplied \& \& rule: 9|Heroes of Comedy~The Goons~The series celebrating great British comics pays tribute to the Goons. \& in : "Heroes of Comedy / " \& out: "Heroes of Comedy / The Goons" \& or \& in : "Heroes of Comedy / Spike Milligan" \& out: "Heroes of Comedy / The Goons" .Ve .IP "\fBprocess_replacement_genres\fR" 4 .IX Item "process_replacement_genres" Rule #6 .Sp Replace <category> with supplied text. .Sp .Vb 2 \& If title matches the rule\*(Aqs text, then use the replacement category(\-ies) supplied \& (note ALL existing categories are replaced) \& \& rule: 6|Antiques Roadshow~Entertainment~Arts~Shopping \& in : "Antiques Roadshow / " category "Reality" \& out: "Antiques Roadshow / " category "Entertainment" + "Arts" + "Shopping" .Ve .Sp You can specify a wildcard with the title by using %% which represents any number of characters. So for example \*(L"News%%\*(R" will match \*(L"News\*(R", \*(L"News and Weather\*(R", \*(L"Newsnight\*(R", etc. But be careful; \*(L"%%News%%\*(R" will also match \*(L"John Craven's Newsround\*(R", \*(L"Eurosport News\*(R", \&\*(L"Election Newsroom Live\*(R", \*(L"Have I Got News For You\*(R", \*(L"Scuzz Meets Jason Newsted\*(R", etc. .IP "\fBprocess_replacement_film_genres\fR" 4 .IX Item "process_replacement_film_genres" Rule #12 .Sp Replace \*(L"Film\*(R"/\*(L"Films\*(R" <category> with supplied text. .Sp .Vb 2 \& If title matches the rule\*(Aqs text and the prog has category "Film" or "Films", then use the replacement category(\-ies) supplied \& (note ALL categories are replaced, not just "Film") \& \& rule: 12|The Hobbit Special~Entertainment~Interview \& in : "The Hobbit Special / " category "Film" + "Drama" \& out: "The Hobbit Special / " category "Entertainment" + "Interview" .Ve .IP "\fBprocess_translate_genres\fR" 4 .IX Item "process_translate_genres" Rule #14 .Sp Replace <category> with supplied value(s). .Sp .Vb 2 \& If category matches one found in the prog, then replace it with the category(\-ies) supplied \& (note any other categories are left alone) \& \& rule: 14|Soccer~Football \& in : "Leeds v Arsenal" category "Soccer" \& out: "Leeds v Arsenal" category "Football" \& \& rule: 14|Adventure/War~Action Adventure~War \& in : "Leeds v Arsenal" category "Adventure/War" \& out: "Leeds v Arsenal" category "Action Adventure" + "War" .Ve .IP "\fBprocess_add_genres_to_channel\fR" 4 .IX Item "process_add_genres_to_channel" Rule #15 .Sp Add a category to all programmes on a specified channel. .Sp .Vb 2 \& If channel matches this prog, the add the supplied category(\-ies) to the programme \& (note any other categories are left alone) \& \& rule: 15|travelchannel.co.uk~Travel \& in : "World\*(Aqs Greatest Motorcycle Rides" category "Motoring" \& out: "World\*(Aqs Greatest Motorcycle Rides" category "Motoring" + "Travel" \& \& rule: 15|cnbc.com~News~Business \& in : "Investing in India" category "" \& out: "Investing in India" category "News" + "Business" .Ve .Sp You should be very careful with this one as it will add the category you specify to \s-1EVERY\s0 programme broadcast on that channel. This may not be what you always want (e.g. Teleshopping isn't really \*(L"music\*(R" even if it is on \s-1MTV\s0!) .IP "\fBprocess_remove_numbering_from_programmes\fR" 4 .IX Item "process_remove_numbering_from_programmes" Rule #16 .Sp Remove episode numbering from a given programme title (on an optionally-specified channel). .Sp .Vb 3 \& If title matches the one in the prog, all programme numbering for the programme \& is removed, on any channel. An optional channel identifier can be provided to \& restrict the removal of programme numbering to the given channel. \& \& rule: 16|Bedtime Story \& in : "CBeebies Bedtime Story" episode\-num ".700." \& out: "CBeebies Bedtime Story" episode\-num "" \& \& rule: 16|CBeebies Bedtime Story~cbeebies.bbc.co.uk \& in : "CBeebies Bedtime Story" episode\-num ".700." \& out: "CBeebies Bedtime Story" episode\-num "" .Ve .Sp Remember to specify the optional channel limiter if you have good programme numbering for a given programme title on some channels but not others. .SH "AUTHOR" .IX Header "AUTHOR" Geoff Westcott, honir.at.gmail.dot.com, Dec. 2014. .PP This code is based on the \*(L"fixup\*(R" method/code defined in tv_grab_uk_rt grabber and credit is given to the author Nick Morrott.