Updates and a bug fix for make_shownotes
Community_News/.make_shownotes.cfg: more comments Community_News/make_email: added colour test for pod2usage Community_News/make_shownotes: fixed a bug when using -lastrecording=DATETIME. Added reporting of expanded output file names; tidying and updates to POD documentation. Community_News/recording_dates.dat: added test entry for May 2025
This commit is contained in:
parent
01d4639ba7
commit
960c5acc83
@ -1,10 +1,12 @@
|
|||||||
#
|
#
|
||||||
# .make_shownotes.cfg (2025-03-27)
|
# .make_shownotes.cfg (2025-04-13)
|
||||||
# Configuration file for make_shownotes version >= 4
|
# Configuration file for make_shownotes version >= 4
|
||||||
#
|
#
|
||||||
<settings>
|
<settings>
|
||||||
|
# Format strings (using 'printf' formatting) for building certain required strings
|
||||||
title_template = HPR Community News for %s %s
|
title_template = HPR Community News for %s %s
|
||||||
summary_template = HPR Volunteers talk about shows released and comments posted in %s %s
|
summary_template = HPR Volunteers talk about shows released and comments posted in %s %s
|
||||||
|
|
||||||
# Repeat the following line with each of the desired tags to make an
|
# Repeat the following line with each of the desired tags to make an
|
||||||
# array-like structure
|
# array-like structure
|
||||||
tags = Community News
|
tags = Community News
|
||||||
@ -27,8 +29,8 @@
|
|||||||
# cache of previous recording dates and times
|
# cache of previous recording dates and times
|
||||||
cache = recording_dates.dat
|
cache = recording_dates.dat
|
||||||
|
|
||||||
# Templates
|
# Template Toolkit templates
|
||||||
# ---------
|
# --------------------------
|
||||||
|
|
||||||
# Main note template (actually a soft link)
|
# Main note template (actually a soft link)
|
||||||
main_template = shownote_template.tpl
|
main_template = shownote_template.tpl
|
||||||
|
@ -47,7 +47,8 @@ use open ':std', ':encoding(UTF-8)'; # Make all IO UTF-8
|
|||||||
use Cwd qw( abs_path );
|
use Cwd qw( abs_path );
|
||||||
|
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
use Pod::Usage;
|
BEGIN { $ENV{PERLDOC} = '-MPod::Text::Color'; }
|
||||||
|
use Pod::Usage qw(pod2usage); # Use colour-capable Pod::Text
|
||||||
|
|
||||||
use Config::General;
|
use Config::General;
|
||||||
|
|
||||||
@ -98,7 +99,7 @@ chdir($basedir);
|
|||||||
# DateTime::TimeZone->all_names(). Just uncomment the desired elements.
|
# DateTime::TimeZone->all_names(). Just uncomment the desired elements.
|
||||||
#
|
#
|
||||||
my @zones = (
|
my @zones = (
|
||||||
#{{{
|
#{{{ --- time zones ---
|
||||||
#'Africa/Abidjan',
|
#'Africa/Abidjan',
|
||||||
#'Africa/Accra',
|
#'Africa/Accra',
|
||||||
#'Africa/Addis_Ababa',
|
#'Africa/Addis_Ababa',
|
||||||
@ -1646,6 +1647,8 @@ The number of the show found in the database.
|
|||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
=head2 B<Overview>
|
||||||
|
|
||||||
The script makes an invitation email for the next Community News recording
|
The script makes an invitation email for the next Community News recording
|
||||||
with times per timezone. The message is structured by a Template Toolkit
|
with times per timezone. The message is structured by a Template Toolkit
|
||||||
template, so its contents can be adjusted without changing this script.
|
template, so its contents can be adjusted without changing this script.
|
||||||
@ -1666,6 +1669,44 @@ to use it with an email client to construct the message to be sent to the HPR
|
|||||||
mailing list, usually on the Monday prior to the weekend of the recording. The
|
mailing list, usually on the Monday prior to the weekend of the recording. The
|
||||||
script does not send the message itself.
|
script does not send the message itself.
|
||||||
|
|
||||||
|
=head2 B<Required files>
|
||||||
|
|
||||||
|
The B<make_email> script requires the presence of two files, which are
|
||||||
|
described in this section. These files are expected to be located in the same
|
||||||
|
directory used to store the script.
|
||||||
|
|
||||||
|
The script also requires a configuration file which is described in the
|
||||||
|
B<CONFIGURATION AND ENVIRONMENT> section below:
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item B<Date Cache>
|
||||||
|
|
||||||
|
This is a file containing the recording dates of previous Community News
|
||||||
|
shows. The file is managed by B<make_email>, and it exists to aid the script
|
||||||
|
B<make_shownotes> when it is generating the HTML notes for distribution to the
|
||||||
|
volunteers who are contributing to the recording.
|
||||||
|
|
||||||
|
When B<make_shownotes> is generating notes for the volunteers it tries to work
|
||||||
|
out whether any comments were missed for that month, or whether any for the
|
||||||
|
current review month were read. It highlights any such cases to assist with
|
||||||
|
continuity. The date and time of the last recording are needed to achieve
|
||||||
|
this.
|
||||||
|
|
||||||
|
The file name is defined in the configuration file, and the default is
|
||||||
|
B<recording_dates.dat>.
|
||||||
|
|
||||||
|
The format of the file is described in the B<DATE CACHE> part of the
|
||||||
|
B<CONFIGURATION AND ENVIRONMENT> section below.
|
||||||
|
|
||||||
|
=item B<Template>
|
||||||
|
|
||||||
|
This is a file written in the Template Toolkit syntax which defines the format
|
||||||
|
of the email text. The name of this file is defined in the configuration file.
|
||||||
|
By default it is B<make_email_template.tpl>.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
=head1 DIAGNOSTICS
|
=head1 DIAGNOSTICS
|
||||||
|
|
||||||
=over 8
|
=over 8
|
||||||
@ -1827,23 +1868,29 @@ is no record for the month being processed, one is appended to the file. If
|
|||||||
the details already exist they are updated unless they are the same as those
|
the details already exist they are updated unless they are the same as those
|
||||||
stored.
|
stored.
|
||||||
|
|
||||||
A backup of the file is made if the data in a record is being updated.
|
A backup of the file is made if the data in a record is being updated. This
|
||||||
|
file has the same name as the cache file with a B<~> character appended to it.
|
||||||
|
|
||||||
=head1 EXAMPLES
|
=head1 EXAMPLES
|
||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
=item 1. Specify a future recording date
|
=item B<Specify a future recording date>
|
||||||
|
|
||||||
make_email -date=2025-08-01
|
make_email -date=2025-08-01
|
||||||
|
|
||||||
Generates the text of an email for a specific date (expected to be in the
|
Generates the text of an email for a specific date (expected to be in the
|
||||||
future). The first Monday of August 2025 is 2025-08-04. The date use in the
|
future). The first Monday of August 2025 is 2025-08-04. The date used in the
|
||||||
example is the Friday before that. The script will compute the month to be
|
example is the Friday before that. The script will compute the month to be
|
||||||
reviewed (July 2025) from this date and write the email message text
|
reviewed (July 2025) from this date and write the email message text
|
||||||
accordingly, to STDOUT.
|
accordingly, to STDOUT.
|
||||||
|
|
||||||
=item 2. Specify and force a review month in the recent past
|
This would be a way of testing the generation of the email text for a future
|
||||||
|
date, as opposed to the next one. It will cause the writing of a record in the
|
||||||
|
data cache file, but, since this will be adjusted if there are any changes in
|
||||||
|
the future, this should not be a problem.
|
||||||
|
|
||||||
|
=item B<Specify and force a review month in the recent past>
|
||||||
|
|
||||||
make_email -force -month=2025-03-01 -start=16:00 -out=HPR_email_%s.txt
|
make_email -force -month=2025-03-01 -start=16:00 -out=HPR_email_%s.txt
|
||||||
|
|
||||||
@ -1855,7 +1902,7 @@ Normally, generating email for March would not be allowed since it's in the
|
|||||||
past, so B<-force> is needed to override the checks. The start day is the
|
past, so B<-force> is needed to override the checks. The start day is the
|
||||||
default Friday, and the start time is set to 16:00. The message (email body)
|
default Friday, and the start time is set to 16:00. The message (email body)
|
||||||
is written to B<HPR_email_2025-03.txt>. The date cache
|
is written to B<HPR_email_2025-03.txt>. The date cache
|
||||||
(B<recording_dates.dat)> will be updated with the line:
|
(B<recording_dates.dat>) will be updated with the line:
|
||||||
|
|
||||||
2025-03-01,2025-04-04 16:00:00
|
2025-03-01,2025-04-04 16:00:00
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
# VERSION: 0.4.4
|
# VERSION: 0.4.4
|
||||||
# ORIGINAL: 2014-04-24 16:08:30
|
# ORIGINAL: 2014-04-24 16:08:30
|
||||||
# CREATED: 2025-03-13 15:07:35
|
# CREATED: 2025-03-13 15:07:35
|
||||||
# REVISION: 2025-04-01 21:29:10
|
# REVISION: 2025-04-15 23:36:56
|
||||||
#
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
|
|
||||||
@ -305,6 +305,9 @@ if (defined($lastrecording)) {
|
|||||||
emit( $silent, "Last recording from option: ", $lastrecording, "\n" );
|
emit( $silent, "Last recording from option: ", $lastrecording, "\n" );
|
||||||
_debug( $DEBUG > 1, '$lastrecording = ' . $lastrecording );
|
_debug( $DEBUG > 1, '$lastrecording = ' . $lastrecording );
|
||||||
|
|
||||||
|
# Compute the last month, with a date
|
||||||
|
@dc_lm = find_last_month(\@review_month);
|
||||||
|
|
||||||
@dc_lr = parse_to_dc( $lastrecording, \@deftime );
|
@dc_lr = parse_to_dc( $lastrecording, \@deftime );
|
||||||
_debug( $DEBUG > 1, '@dc_lr = ' . Dumper( \@dc_lr ) );
|
_debug( $DEBUG > 1, '@dc_lr = ' . Dumper( \@dc_lr ) );
|
||||||
}
|
}
|
||||||
@ -417,7 +420,8 @@ else {
|
|||||||
"Error: episode $episode already exists in the database\n");
|
"Error: episode $episode already exists in the database\n");
|
||||||
|
|
||||||
if ($h1->{title} eq $title) {
|
if ($h1->{title} eq $title) {
|
||||||
say "(Episode $episode is an old-style place-holder. Continuing)";
|
emit( $silent,
|
||||||
|
"(Episode $episode is an old-style place-holder. Continuing)\n");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
die "Trying to overwrite an existing show. Aborting\n";
|
die "Trying to overwrite an existing show. Aborting\n";
|
||||||
@ -451,7 +455,7 @@ for my $file (
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
emit( $silent, sprintf( "* %-100s *\n", "» $file" ) );
|
emit( $silent, sprintf( "* %-100s *\n", "> $file" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
emit($silent,"\n");
|
emit($silent,"\n");
|
||||||
@ -487,6 +491,8 @@ emit(
|
|||||||
)
|
)
|
||||||
) if $t_time;
|
) if $t_time;
|
||||||
|
|
||||||
|
emit($silent,"\n");
|
||||||
|
|
||||||
#
|
#
|
||||||
# Report what we have in the 'lastrecording' and 'lastmonth' variables
|
# Report what we have in the 'lastrecording' and 'lastmonth' variables
|
||||||
#
|
#
|
||||||
@ -913,10 +919,17 @@ if ($html_outfile || $json_outfile) {
|
|||||||
# Settings for creating the HTML fragment
|
# Settings for creating the HTML fragment
|
||||||
#
|
#
|
||||||
if ($html_outfile) {
|
if ($html_outfile) {
|
||||||
$outfh = make_filename_and_open($html_outfile,
|
#
|
||||||
|
# We get the file handle and the expanded filename
|
||||||
|
#
|
||||||
|
($outfh,$html_outfile) = make_filename_and_open($html_outfile,
|
||||||
sprintf( "%d-%02d", $dt_som->year, $dt_som->month ));
|
sprintf( "%d-%02d", $dt_som->year, $dt_som->month ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# We generate the HTML fragment whether we're to write it or not, since
|
||||||
|
# it's needed for making JSON
|
||||||
|
#
|
||||||
my $vars = {
|
my $vars = {
|
||||||
review_month => $dt_som->month_name,
|
review_month => $dt_som->month_name,
|
||||||
review_year => $dt_som->year,
|
review_year => $dt_som->year,
|
||||||
@ -951,13 +964,18 @@ if ($html_outfile || $json_outfile) {
|
|||||||
if ($html_outfile) {
|
if ($html_outfile) {
|
||||||
print $outfh $document;
|
print $outfh $document;
|
||||||
close($outfh);
|
close($outfh);
|
||||||
|
|
||||||
|
#
|
||||||
|
# Report the output file
|
||||||
|
#
|
||||||
|
emit($silent,"HTML is in $html_outfile\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Create the JSON if requested
|
# Create the JSON if requested
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
if ($json_outfile) {
|
if ($json_outfile) {
|
||||||
$outfh = make_filename_and_open($json_outfile,
|
($outfh, $json_outfile) = make_filename_and_open($json_outfile,
|
||||||
sprintf( "%d-%02d", $dt_som->year, $dt_som->month ));
|
sprintf( "%d-%02d", $dt_som->year, $dt_som->month ));
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -1005,6 +1023,11 @@ if ($html_outfile || $json_outfile) {
|
|||||||
my $json = JSON->new->utf8;
|
my $json = JSON->new->utf8;
|
||||||
say $outfh $json->encode(\%json_data);
|
say $outfh $json->encode(\%json_data);
|
||||||
|
|
||||||
|
#
|
||||||
|
# Report the output file
|
||||||
|
#
|
||||||
|
emit($silent,"JSON is in $json_outfile\n");
|
||||||
|
|
||||||
$sth1->finish;
|
$sth1->finish;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1015,10 +1038,12 @@ if ($html_outfile || $json_outfile) {
|
|||||||
# standalone.
|
# standalone.
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
if ($full_html_outfile) {
|
if ($full_html_outfile) {
|
||||||
|
my $outfh;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Settings for creating the standalone HTML
|
# Settings for creating the standalone HTML
|
||||||
#
|
#
|
||||||
my $outfh = make_filename_and_open($full_html_outfile,
|
($outfh,$full_html_outfile) = make_filename_and_open($full_html_outfile,
|
||||||
sprintf( "%d-%02d", $dt_som->year, $dt_som->month ));
|
sprintf( "%d-%02d", $dt_som->year, $dt_som->month ));
|
||||||
|
|
||||||
my $vars = {
|
my $vars = {
|
||||||
@ -1061,6 +1086,11 @@ if ($full_html_outfile) {
|
|||||||
|| die $tt->error(), "\n";
|
|| die $tt->error(), "\n";
|
||||||
|
|
||||||
print $outfh $full_document;
|
print $outfh $full_document;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Report the output file
|
||||||
|
#
|
||||||
|
emit($silent,"Full HTML is in $full_html_outfile\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
$dbh->disconnect;
|
$dbh->disconnect;
|
||||||
@ -1600,7 +1630,7 @@ sub ISO8601_Date {
|
|||||||
# the file for output
|
# the file for output
|
||||||
# PARAMETERS: $filename Name of file with or without '%s'
|
# PARAMETERS: $filename Name of file with or without '%s'
|
||||||
# $subs String to substitute for '%s'
|
# $subs String to substitute for '%s'
|
||||||
# RETURNS: File handle
|
# RETURNS: A list containing the file handle and the expanded filename
|
||||||
# DESCRIPTION:
|
# DESCRIPTION:
|
||||||
# THROWS: No exceptions
|
# THROWS: No exceptions
|
||||||
# COMMENTS: None
|
# COMMENTS: None
|
||||||
@ -1618,7 +1648,7 @@ sub make_filename_and_open {
|
|||||||
open( $outfh, ">:encoding(UTF-8)", $filename )
|
open( $outfh, ">:encoding(UTF-8)", $filename )
|
||||||
or croak "Unable to open $filename for writing: $!";
|
or croak "Unable to open $filename for writing: $!";
|
||||||
|
|
||||||
return $outfh;
|
return ($outfh,$filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
#=== FUNCTION ================================================================
|
#=== FUNCTION ================================================================
|
||||||
@ -1959,8 +1989,6 @@ Reports the following (as well as the data for level 1):
|
|||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
=item .
|
|
||||||
|
|
||||||
Details of the last recording data (and time)
|
Details of the last recording data (and time)
|
||||||
|
|
||||||
=back
|
=back
|
||||||
@ -1971,8 +1999,6 @@ Reports the following (as well as the data for level 2):
|
|||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
=item .
|
|
||||||
|
|
||||||
The generation of comment indexes needed in the comment lists. These are
|
The generation of comment indexes needed in the comment lists. These are
|
||||||
computed after the query has been run.
|
computed after the query has been run.
|
||||||
|
|
||||||
@ -1987,26 +2013,16 @@ Reports the following (as well as the data for level 3):
|
|||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
=item .
|
|
||||||
|
|
||||||
A dump of the '%past' hash which contains details of comments on past shows.
|
A dump of the '%past' hash which contains details of comments on past shows.
|
||||||
|
|
||||||
=item .
|
|
||||||
|
|
||||||
A dump of the '%current' hash which contains details of comments on this
|
A dump of the '%current' hash which contains details of comments on this
|
||||||
month's shows.
|
month's shows.
|
||||||
|
|
||||||
=item .
|
|
||||||
|
|
||||||
A dump of the '@missed_comments' array containing comments that arrived after
|
A dump of the '@missed_comments' array containing comments that arrived after
|
||||||
the last recording.
|
the last recording.
|
||||||
|
|
||||||
=item .
|
|
||||||
|
|
||||||
A list of the duplicated episode numbers in '@missed_episodes'
|
A list of the duplicated episode numbers in '@missed_episodes'
|
||||||
|
|
||||||
=item .
|
|
||||||
|
|
||||||
Another dump of '%past' after it has been cleaned up. Also the count of
|
Another dump of '%past' after it has been cleaned up. Also the count of
|
||||||
comments to past shows and the comment count.
|
comments to past shows and the comment count.
|
||||||
|
|
||||||
@ -2076,22 +2092,22 @@ Four types of information are collected by the script:
|
|||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
=item -
|
=item B<Host details>
|
||||||
|
|
||||||
Details of new hosts who have released new shows in the selected month
|
Details of new hosts who have released new shows in the selected month
|
||||||
|
|
||||||
=item -
|
=item B<Show details>
|
||||||
|
|
||||||
Details of shows which have been released in the selected month
|
Details of shows which have been released in the selected month
|
||||||
|
|
||||||
=item -
|
=item B<Comments>
|
||||||
|
|
||||||
Comments which have been submitted to the HPR website in the selected month.
|
Comments which have been submitted to the HPR website in the selected month.
|
||||||
These need to be related to shows in the current period or in the past.
|
These need to be related to shows in the current period or in the past.
|
||||||
Comments made about shows which have not yet been released (but are visible on
|
Comments made about shows which have not yet been released (but are visible on
|
||||||
the website) are not included even though they are made in the current month.
|
the website) are not included even though they are made in the current month.
|
||||||
|
|
||||||
=item -
|
=item B<Mailing list threads>
|
||||||
|
|
||||||
A link to the current threads on the mailing list in the past month can be included. This
|
A link to the current threads on the mailing list in the past month can be included. This
|
||||||
is done by default but can be skipped if the B<-nomailnotes> option is used.
|
is done by default but can be skipped if the B<-nomailnotes> option is used.
|
||||||
@ -2137,7 +2153,7 @@ If you wish to write your own template refer to the following lists for the
|
|||||||
names of items. Also refer to the default template B<shownote_template.tpl>
|
names of items. Also refer to the default template B<shownote_template.tpl>
|
||||||
for the techniques used there. (Note that B<shownote_template.tpl> is a soft
|
for the techniques used there. (Note that B<shownote_template.tpl> is a soft
|
||||||
link to the current default template, such as B<shownote_template12.tpl>, the
|
link to the current default template, such as B<shownote_template12.tpl>, the
|
||||||
link name is currently used in the configuration file).
|
soft link name is currently used in the configuration file).
|
||||||
|
|
||||||
The hash and field names available to the template are as follows
|
The hash and field names available to the template are as follows
|
||||||
|
|
||||||
@ -2359,12 +2375,14 @@ The configuration file contains the following settings, which are explained
|
|||||||
at the end.
|
at the end.
|
||||||
|
|
||||||
#
|
#
|
||||||
# .make_shownotes.cfg (2025-03-27)
|
# .make_shownotes.cfg (2025-04-13)
|
||||||
# Configuration file for make_shownotes version >= 4
|
# Configuration file for make_shownotes version >= 4
|
||||||
#
|
#
|
||||||
<settings>
|
<settings>
|
||||||
|
# Format strings (using 'printf' formatting) for building certain required strings
|
||||||
title_template = HPR Community News for %s %s
|
title_template = HPR Community News for %s %s
|
||||||
summary_template = HPR Volunteers talk about shows released and comments posted in %s %s
|
summary_template = HPR Volunteers talk about shows released and comments posted in %s %s
|
||||||
|
|
||||||
# Repeat the following line with each of the desired tags to make an
|
# Repeat the following line with each of the desired tags to make an
|
||||||
# array-like structure
|
# array-like structure
|
||||||
tags = Community News
|
tags = Community News
|
||||||
@ -2387,8 +2405,8 @@ at the end.
|
|||||||
# cache of previous recording dates and times
|
# cache of previous recording dates and times
|
||||||
cache = recording_dates.dat
|
cache = recording_dates.dat
|
||||||
|
|
||||||
# Templates
|
# Template Toolkit templates
|
||||||
# ---------
|
# --------------------------
|
||||||
|
|
||||||
# Main note template (actually a soft link)
|
# Main note template (actually a soft link)
|
||||||
main_template = shownote_template.tpl
|
main_template = shownote_template.tpl
|
||||||
@ -2404,7 +2422,7 @@ at the end.
|
|||||||
name = hpr.db
|
name = hpr.db
|
||||||
</database>
|
</database>
|
||||||
|
|
||||||
=head2 Details
|
=head2 Configuration file details
|
||||||
|
|
||||||
If any mandatory elements are omitted from the configuration file they are
|
If any mandatory elements are omitted from the configuration file they are
|
||||||
given default values in the script.
|
given default values in the script.
|
||||||
|
@ -31,3 +31,4 @@
|
|||||||
2025-01-01,2025-01-31 15:00:00
|
2025-01-01,2025-01-31 15:00:00
|
||||||
2025-02-01,2025-02-28 16:00:00
|
2025-02-01,2025-02-28 16:00:00
|
||||||
2025-03-01,2025-04-04 16:00:00
|
2025-03-01,2025-04-04 16:00:00
|
||||||
|
2025-04-01,2025-05-02 16:00:00
|
||||||
|
Loading…
x
Reference in New Issue
Block a user