Updates for Community News tools
Community_News/make_email: minor tidying Community_News/make_shownotes: addition of File::Copy; addition of cache management routines; cache is now managed here as well as in 'make_email'; fixed a bug with use of '$/'; POD enhancements. Community_News/recording_dates.dat: for reference Community_News/shownote_template12.tpl: removed the "Updated on" section. Community_News/shownotes_container.tpl: enhanced the datestamp header when generating "full" shownotes.
This commit is contained in:
@@ -29,10 +29,10 @@
|
||||
# Where pod2pdf comes from App::pod2pdf
|
||||
#
|
||||
# AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com
|
||||
# VERSION: 0.4.4
|
||||
# VERSION: 0.4.5
|
||||
# ORIGINAL: 2014-04-24 16:08:30
|
||||
# CREATED: 2025-03-13 15:07:35
|
||||
# REVISION: 2025-04-17 15:12:27
|
||||
# REVISION: 2025-08-09 11:28:22
|
||||
#
|
||||
#===============================================================================
|
||||
|
||||
@@ -51,6 +51,8 @@ use Pod::Usage qw(pod2usage); # Use colour-capable Pod::Text
|
||||
|
||||
use Config::General;
|
||||
|
||||
use File::Copy;
|
||||
|
||||
use Date::Parse;
|
||||
use Date::Calc qw{:all};
|
||||
use DateTime;
|
||||
@@ -71,7 +73,7 @@ use Data::Dumper;
|
||||
#
|
||||
# Version number (manually incremented)
|
||||
#
|
||||
our $VERSION = '0.4.4';
|
||||
our $VERSION = '0.4.5';
|
||||
|
||||
#
|
||||
# Various constants
|
||||
@@ -103,14 +105,13 @@ my $defseries_id = 47;
|
||||
my $defcache = "$basedir/recording_dates.dat";
|
||||
my $defcontainer = "$basedir/shownotes_container.tpl";
|
||||
|
||||
my ( $dbh, $sth1, $h1 );
|
||||
my ( @review_month, $releasedate, @releasedate, $hosts, $shows, $episode );
|
||||
my ( @dc_lr, $dt_lr, @dc_lm, $dt_lm, @dc_rd, $dt_rd );
|
||||
my ( %attributes );
|
||||
my ( %date_cache, $date_offset, @deftime );
|
||||
my ( $t_time, $missed_comments, $missed_count );
|
||||
my ( $comments, $comment_count, $past_count, $ignore_count );
|
||||
my ( %past, %current );
|
||||
my ( $dbh, $sth1, $h1 );
|
||||
my ( @review_month, $releasedate, @releasedate, $hosts, $shows, $episode );
|
||||
my ( @dc_lr, $dt_lr, @dc_lm, $dt_lm, @dc_rd, $dt_rd );
|
||||
my ( %attributes, %date_cache, $lr_option_status, $date_offset, @deftime );
|
||||
my ( $t_time, $missed_comments, $missed_count );
|
||||
my ( $comments, $comment_count, $past_count, $ignore_count );
|
||||
my ( %past, %current );
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# The structure of the JSON to be sent to the HPR server
|
||||
@@ -195,8 +196,8 @@ my $json_outfile = $options{json};
|
||||
die "Unable to find configuration file $cfgfile\n" unless ( -e $cfgfile );
|
||||
|
||||
#
|
||||
# We're receiving the datetime for the last recording (that's the recording
|
||||
# for the previous month), which isn't appropriate unless we're marking
|
||||
# If we're receiving the datetime for the last recording (that's the recording
|
||||
# for the previous month), it isn't appropriate unless we're marking
|
||||
# comments.
|
||||
#
|
||||
if (defined($lastrecording)) {
|
||||
@@ -204,6 +205,11 @@ if (defined($lastrecording)) {
|
||||
unless defined($full_html_outfile);
|
||||
}
|
||||
|
||||
#
|
||||
# Record whether or not we got a -lastrecording=DATETIME option
|
||||
#
|
||||
$lr_option_status = defined($lastrecording);
|
||||
|
||||
#
|
||||
# One at least of the output files must be present
|
||||
#
|
||||
@@ -213,7 +219,7 @@ unless ($full_html_outfile || $html_outfile || $json_outfile) {
|
||||
die "Missing output file option\n";
|
||||
}
|
||||
|
||||
say "DEBUG level is %d", $DEBUG if $DEBUG > 0;
|
||||
say "DEBUG level is $DEBUG" if $DEBUG > 0;
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Use the date provided for the review month or use today's date as the default
|
||||
@@ -231,6 +237,7 @@ else {
|
||||
@review_month = Today();
|
||||
}
|
||||
$review_month[2] = 1;
|
||||
_debug( $DEBUG > 1, '@review_month = ' . Dumper( \@review_month ) );
|
||||
@dc_lm = @review_month; # TODO: Is this right?
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
@@ -238,9 +245,9 @@ $review_month[2] = 1;
|
||||
#-------------------------------------------------------------------------------
|
||||
emit( $silent, "Configuration file: ", $cfgfile, "\n" );
|
||||
my $conf = Config::General->new(
|
||||
-ConfigFile => $cfgfile,
|
||||
-InterPolateVars => 1,
|
||||
-ExtendedAccess => 1,
|
||||
-ConfigFile => $cfgfile,
|
||||
-InterPolateVars => 1,
|
||||
-ExtendedAccess => 1,
|
||||
-UseApacheInclude => 1,
|
||||
);
|
||||
my %config = $conf->getall();
|
||||
@@ -291,6 +298,11 @@ $tags = [$tags] unless ( ref($tags) eq 'ARRAY' );
|
||||
@deftime = split( ':', $start_time );
|
||||
my $release_dow = Decode_Day_of_Week($release_day);
|
||||
|
||||
#
|
||||
# Report the date cache name before working on it.
|
||||
#
|
||||
emit( $silent, "Date cache: ", $date_cache_name, "\n" );
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Set last recording date and time from option or cache
|
||||
#-------------------------------------------------------------------------------
|
||||
@@ -298,18 +310,38 @@ my $release_dow = Decode_Day_of_Week($release_day);
|
||||
# recording for the previous month) as an option, or we'll check the
|
||||
# cache.
|
||||
#
|
||||
if (defined($lastrecording)) {
|
||||
if ($lr_option_status) {
|
||||
#
|
||||
# Parse and perform rudimentary validation on the -lastrecording option
|
||||
# The -lastrecording option is present, so parse and perform rudimentary
|
||||
# validation on the values.
|
||||
#
|
||||
emit( $silent, "Last recording from option: ", $lastrecording, "\n" );
|
||||
_debug( $DEBUG > 1, '$lastrecording = ' . $lastrecording );
|
||||
|
||||
# Compute the last month, with a date
|
||||
@dc_lm = find_last_month(\@review_month);
|
||||
_debug( $DEBUG > 1, '@dc_lm = ' . Dumper( \@dc_lm ) );
|
||||
|
||||
@dc_lr = parse_to_dc( $lastrecording, \@deftime );
|
||||
_debug( $DEBUG > 1, '@dc_lr = ' . Dumper( \@dc_lr ) );
|
||||
|
||||
#
|
||||
# Validate the provided lastrecording date which should be a few days
|
||||
# before the start of the review month or into the next month. This will
|
||||
# make it between 26 and 35 days from the start of the previous month.
|
||||
#
|
||||
my $lr_delta_days
|
||||
= abs( Delta_Days( @dc_lm[ 0 .. 2 ], @dc_lr[ 0 .. 2 ] ) );
|
||||
_debug(
|
||||
$DEBUG > 1,
|
||||
'Difference between @dc_lm and @dc_lr: ' . $lr_delta_days
|
||||
);
|
||||
if ($lr_delta_days < 26 || $lr_delta_days > 35) {
|
||||
say "Problem with -lastrecording=DATETIME specification.";
|
||||
say "Difference between given date and start of the month before ",
|
||||
"the review month is $lr_delta_days days";
|
||||
die "Can't continue\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
emit( $silent, "Getting last recording from cache\n" );
|
||||
@@ -317,7 +349,6 @@ else {
|
||||
#
|
||||
# Load the cache
|
||||
#
|
||||
emit( $silent, "Date cache: ", $date_cache_name, "\n" );
|
||||
%date_cache = load_cache($date_cache_name);
|
||||
#_debug( $DEBUG > 1, '%date_cache = ' . Dumper(\%date_cache) );
|
||||
|
||||
@@ -331,8 +362,8 @@ else {
|
||||
# Abort if the cache didn't have the date
|
||||
#
|
||||
unless (defined($lastrecording)) {
|
||||
say "The date and time of the last recording is not in the cache";
|
||||
say "Use option -lastrecording=DATETIME (or -lr=DATETIME) instead";
|
||||
say "The date and time of the last recording is not in the cache. Use";
|
||||
say "option -lastrecording=DATETIME (or -lr=DATETIME) to define them.";
|
||||
die "Can't continue\n";
|
||||
}
|
||||
|
||||
@@ -752,7 +783,7 @@ if ($show_comments) {
|
||||
#
|
||||
if ( $full_html_outfile ) {
|
||||
{
|
||||
$/ = '';
|
||||
local $/ = '';
|
||||
chomp($row->{comment_text}); # NOTE: experimental
|
||||
}
|
||||
}
|
||||
@@ -909,6 +940,48 @@ my $tt = Template->new(
|
||||
}
|
||||
);
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Update the cache from the -lastrecording=DATETIME option if needed
|
||||
#-------------------------------------------------------------------------------
|
||||
if ($lr_option_status) {
|
||||
#
|
||||
# We were given the last recording as an option. The most likely reason is
|
||||
# that it's not in the cache, but it may contain a correction. Look to
|
||||
# see if it is in the cache, and if so, whether it's the same. Add it if
|
||||
# it's missing or update it unless it agrees.
|
||||
#
|
||||
emit( $silent, "Loading recording date cache\n" );
|
||||
|
||||
#
|
||||
# Load the cache
|
||||
#
|
||||
%date_cache = load_cache($date_cache_name);
|
||||
#_debug( $DEBUG > 1, '%date_cache = ' . Dumper(\%date_cache) );
|
||||
|
||||
#
|
||||
# Create the month key from the month before the review month, then see if
|
||||
# it's already in the cache. The date of the start of last month is in
|
||||
# $dt_lm.
|
||||
#
|
||||
my $monthkey = sprintf( "%d-%02d-01", $dt_lm->year, $dt_lm->month );
|
||||
|
||||
#
|
||||
# If the key is not in the %date_cache OR if it's already there but the
|
||||
# value part doesn't match the last recording specification run
|
||||
# update_cache to make changes. The tests are made in this order so we
|
||||
# don't try and reference a non-existent element.
|
||||
#
|
||||
if (!exists( $date_cache{$monthkey} )
|
||||
|| ( exists( $date_cache{$monthkey} )
|
||||
&& ( $date_cache{$monthkey} ne $lastrecording ) )
|
||||
)
|
||||
{
|
||||
$date_cache{$monthkey} = $lastrecording;
|
||||
update_cache( $date_cache_name, \%date_cache );
|
||||
emit( $silent, "Updated date cache\n" );
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Generate the HTML fragment and add it to the JSON if that output is requested
|
||||
#-------------------------------------------------------------------------------
|
||||
@@ -1307,7 +1380,14 @@ sub dc_to_dt {
|
||||
# PURPOSE: Load the date cache into a hash
|
||||
# PARAMETERS: $cache_name Name of file holding the cache
|
||||
# RETURNS: Contents of cache as a hash
|
||||
# DESCRIPTION:
|
||||
# DESCRIPTION: Opens the nominated file, parses each record, and adds the
|
||||
# data to a hash. The record should contain the following:
|
||||
# * 'YYYY-MM-01' the month for which the details are being
|
||||
# recorded
|
||||
# * ',' comma field separator
|
||||
# * 'YYYY-MM-DD HH:MM:SS' timestamp of the recording
|
||||
# The file is closed once it has been scanned. The function
|
||||
# returns the completed hash.
|
||||
# THROWS: No exceptions
|
||||
# COMMENTS: None
|
||||
# SEE ALSO: N/A
|
||||
@@ -1317,24 +1397,102 @@ sub load_cache {
|
||||
|
||||
my ( $month, $datetime, %result );
|
||||
|
||||
open( my $dc, '<', $cache_name )
|
||||
or die "$0 : failed to open '$cache_name': $!\n";
|
||||
#
|
||||
# Open the file in read mode
|
||||
#
|
||||
open( my $dcfh, '<', $cache_name )
|
||||
or die "$PROG: failed to open '$cache_name': $!\n";
|
||||
|
||||
while ( my $line = <$dc> ) {
|
||||
while ( my $line = <$dcfh> ) {
|
||||
chomp($line);
|
||||
if ( ( $month, $datetime )
|
||||
= ( $line =~ /^(\d{4}-\d{2}-\d{2}),(.*)$/ ) )
|
||||
{
|
||||
$result{$month} = $datetime;
|
||||
}
|
||||
# TODO: Report any errors found in the file
|
||||
}
|
||||
|
||||
close($dc)
|
||||
or warn "$0 : failed to close '$cache_name': $!\n";
|
||||
close($dcfh)
|
||||
or warn "${PROG}: failed to close '$cache_name': $!\n";
|
||||
|
||||
return %result;
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: append_cache
|
||||
# PURPOSE: Append a new line to the cache
|
||||
# PARAMETERS: $cache_name Name of file holding the cache
|
||||
# $line New record to add
|
||||
# RETURNS: Nothing
|
||||
# DESCRIPTION: Opens the nominated file and appends the new record in $line.
|
||||
# The file is closed once it has been updated.
|
||||
# THROWS: No exceptions
|
||||
# COMMENTS: None
|
||||
# SEE ALSO: N/A
|
||||
#===============================================================================
|
||||
sub append_cache {
|
||||
my ( $cache_name, $line ) = @_;
|
||||
|
||||
#
|
||||
# Open the file in append mode
|
||||
#
|
||||
open( my $dcfh, '>>', $cache_name )
|
||||
or die "$PROG: failed to open '$cache_name': $!\n";
|
||||
|
||||
say $dcfh $line;
|
||||
|
||||
close($dcfh)
|
||||
or warn "${PROG}: failed to close '$cache_name': $!\n";
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: update_cache
|
||||
# PURPOSE: Make changes to an existing line in the cache
|
||||
# PARAMETERS: $cache_name Name of file holding the cache
|
||||
# $rhash Hashref holding the updated cache contents
|
||||
# RETURNS: Nothing
|
||||
# DESCRIPTION: Makes a backup of the nominated file. Opens, truncates it and
|
||||
# positions for writing (using 'seek'). The now empty file is
|
||||
# filled with data from the hash and closed.
|
||||
# THROWS: No exceptions
|
||||
# COMMENTS: Uses 'copy' from File::Copy
|
||||
# SEE ALSO: N/A
|
||||
#===============================================================================
|
||||
sub update_cache {
|
||||
my ( $cache_name, $rhash ) = @_;
|
||||
|
||||
#
|
||||
# Copy the cache file to a backup
|
||||
#
|
||||
copy($cache_name,"${cache_name}~")
|
||||
or die "Unable to back up '$cache_name'\n";
|
||||
|
||||
#
|
||||
# Open the original file in write mode
|
||||
#
|
||||
open( my $dcfh, '>', $cache_name )
|
||||
or die "${PROG}: failed to open '$cache_name': $!\n";
|
||||
|
||||
#
|
||||
# Truncate the file and seek to the start again
|
||||
#
|
||||
truncate($dcfh,0)
|
||||
or die "${PROG}: failed to truncate '$cache_name': $!\n";
|
||||
seek($dcfh,0,0)
|
||||
or die "$PROG: failed to seek in '$cache_name': $!\n";
|
||||
|
||||
#
|
||||
# Write the cache data to the file
|
||||
#
|
||||
for my $key (sort(keys(%$rhash))) {
|
||||
say $dcfh sprintf("%s,%s",$key, $rhash->{$key});
|
||||
}
|
||||
|
||||
close($dcfh)
|
||||
or warn "${PROG}: failed to close '$cache_name': $!\n";
|
||||
}
|
||||
|
||||
#=== FUNCTION ================================================================
|
||||
# NAME: find_last_month
|
||||
# PURPOSE: Finds the previous month for working out marks
|
||||
@@ -1811,7 +1969,7 @@ make_shownotes - Make show notes for the Hacker Public Radio Community News show
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
This documentation refers to B<make_shownotes> version 0.4.4
|
||||
This documentation refers to B<make_shownotes> version 0.4.5
|
||||
|
||||
|
||||
=head1 USAGE
|
||||
@@ -1924,19 +2082,49 @@ This will cause the generation of the file:
|
||||
|
||||
=item B<-lastrecording=DATETIME> or B<-lr=DATETIME>
|
||||
|
||||
As mentioned for B<-full-html=FILE>, the script needs the date of the last
|
||||
recording when marking comments. This can be extracted from the file
|
||||
referenced in the configuration data using the setting B<cache>. By default
|
||||
the name of this file is B<recording_dates.dat>, and its contents are managed
|
||||
when the script B<make_email> is run.
|
||||
As mentioned for B<-full-html=FILE>, and later in the I<MARKING COMMENTS>
|
||||
section, the script needs the date of the last recording when marking
|
||||
comments. This can be extracted from the file referenced in the configuration
|
||||
data using the setting B<cache>. By default the name of this file is
|
||||
B<recording_dates.dat>, and its contents are managed when the script
|
||||
B<make_email> is run and by this script.
|
||||
|
||||
If for any reason the date and time of the last recording is missing, these
|
||||
values can be defined with this option.
|
||||
values can be defined with this option, and these values will be written to
|
||||
the cache file (or modified, if necessary).
|
||||
|
||||
The format can be an ISO 8601 date followed by a 24-hour time, such as
|
||||
'2020-01-25 15:00'. If the time is omitted it defaults to the value of
|
||||
'2020-01-25 15:00:00'. If the time is omitted it defaults to the value of
|
||||
I<starttime> in the configuration file.
|
||||
|
||||
The script will update the cache file with the date and time used in this
|
||||
option if the relevant entry is missing. Also, if an entry is present but the
|
||||
values are different from those provided with the option, the relevant entry
|
||||
will be updated.
|
||||
|
||||
Note that the B<DATETIME> value must contain the date of the last recording.
|
||||
This will be checked, and written to the cache file prefixed by a "key"
|
||||
consisting of the first day of the month I<BEFORE> the month being reviewed.
|
||||
|
||||
For example, when generating the notes for August 2025 the following command
|
||||
will be needed if there is no last recording date (for July 2025) in the
|
||||
cache:
|
||||
|
||||
./make_shownotes -from=2025-08-01 -full-html=full_shownotes_%s.html \
|
||||
-mail -comments -lr="2025-08-01 15:00:00"
|
||||
|
||||
Here we need the last recording date for the show reviewing HPR shows in July
|
||||
2025. The date and time for this recording was in early August (Friday before
|
||||
the first Monday of September 2025-09-01), as shown. This combination will
|
||||
result in the addition of the following line to the cache file:
|
||||
|
||||
2025-07-01,2025-08-01 15:00:00
|
||||
|
||||
As mentioned, the addition of such date and time information to the cache will
|
||||
normally be performed by B<make_email>, which performs the date computations
|
||||
itself, unlike this script. This feature in this script is an alternative for
|
||||
special cases.
|
||||
|
||||
=item B<-[no]silent>
|
||||
|
||||
This option controls whether the script reports details of its progress
|
||||
@@ -2501,6 +2689,7 @@ Modules used:
|
||||
Date::Parse
|
||||
DateTime::Duration
|
||||
DateTime
|
||||
File::Copy
|
||||
Getopt::Long
|
||||
HTML::Entities
|
||||
JSON
|
||||
|
Reference in New Issue
Block a user