#!/usr/bin/perl -w
#
# awards.pl -- Give out awards to worth MILHIST members
# Usage: awards.pl
# 19 Feb 2018 Created
use English;
use strict;
use utf8;
use warnings;
use DateTime;
use File::Basename;
use MediaWiki::Bot;
my $dt = DateTime->today();
$dt->add (days => $dt->month_length - $dt->day + 1);
my $month = $dt->strftime ("%B %Y");
my $nominations_page = 'Wikipedia talk:WikiProject Military history/Awards';
my $bugle_page = join '/', 'Wikipedia:WikiProject Military history', 'News', $month, 'Project news';
# Test pages
my $debug = 0;
if ($debug) {
$nominations_page = 'User:Hawkeye7/Sandbox2';
$bugle_page = 'User:Hawkeye7/Sandbox7';
}
binmode(STDOUT, ":utf8");
binmode(STDERR, ":utf8");
my $dirname = dirname (__FILE__, '.pl');
push @INC, $dirname;
require Cred;
my $cred = new Cred ();
my $log = $cred->log ();
# log in to the wiki
my $editor = MediaWiki::Bot->new({
host => 'en.wikipedia.org',
assert => 'bot',
protocol => 'https',
operator => 'Hawekeye7',
}) or die "new MediaWiki::Bot failed";
$editor->login ({
username => $cred->user,
password => $cred->password
}) or die $editor->{error}->{code} . ': ' . $editor->{error}->{details};
sub error_exit ($) {
my @message = @ARG;
if ($editor->{error}->{code}) {
push @message, ' (', $editor->{error}->{code} , ') : ' , $editor->{error}->{details};
}
$cred->error (@message);
}
sub error_warning ($) {
my @message = @ARG;
if ($editor->{error}->{code}) {
push @message, ' (', $editor->{error}->{code} , ') : ' , $editor->{error}->{details};
}
$cred->warning (@message);
}
sub parse_template ($@) {
my ($text, @args) = @ARG;
my %p;
while ($text =~ s/\|(\w+)\s*=\s*([^}|]+)//is) {
$p{$1}=$2;
}
my @p = split '\|', $text;
param:foreach my $p (@p) {
next param unless $p;
foreach my $arg (@args) {
if (!defined $p{$arg}) {
$p{$arg} = $p;
next param;
}
}
}
# foreach my $p (keys %p) {
# print "$p => $p{$p}\n";
# }
return \%p;
}
sub notify_recipient ($) {
my $award = shift;
my $user_talk_page = 'User talk:' . $award->{nominee};
my $user_talk_text = $editor->get_text ($user_talk_page) or
error_exit ("Unable to find '$user_talk_page')");
$cred->error ("no bots allowed on '$user_talk_page'") unless $cred->allow_bots ($user_talk_text);
my $templates = {
'A-Class medal' => 'WPMILHIST A-Class medal',
'A-Class medal with Oak Leaves' => 'WPMILHIST A-Class medal (Oakleaves)',
'A-Class medal with Swords' => 'WPMILHIST A-Class medal (Swords)',
'A-Class medal with Diamond' => 'WPMILHIST A-Class medal (Diamonds)',
'A-Class cross' => 'WPMILHIST A-Class cross',
'A-Class cross with Oak Leaves' => 'WPMILHIST A-Class cross with Oak Leaves',
'A-Class cross with Swords' => 'WPMILHIST A-Class cross with Swords',
'A-Class cross with Diamond' => 'WPMILHIST A-Class cross with Diamonds',
};
my $template = $templates->{$award->{award}} or
$cred->error ("unknown award: '$award->{award}'\n");
$user_talk_text .= "\n==Congratulations from the Military History Project==\n{{subst:$template|1=On behalf of the Military History I am proud to present the $award->{award} for $award->{citation} ~~~~}}\n";
$cred->showtime ("\tAdding award to $user_talk_page\n");
$editor->edit ({
page => $user_talk_page,
text => $user_talk_text,
summary => "Awarded $award->{award} to $award->{nominee}",
minor => 0,
}) or
error_exit ("unable to edit '$user_talk_page'");
my @history = $editor->get_history ($user_talk_page, 2) or
error_exit "Unable get history of '$user_talk_page'";
$award->{diff} = $history[0]->{revid};
$award->{oldid} = $history[1]->{revid};
}
sub add_to_historical_list ($) {
my $award = shift;
sub entry ($) {
my $award = shift;
return "* [[User:$award->{nominee}|$award->{nominee}]]: $award->{citation} (Awarded {{diff|page=User talk:$award->{nominee}|diff=$award->{diff}|oldid=$award->{oldid}}|label=$month}})";
}
my $award_pages = {
# 'WikiChevrons' => 'Wikipedia:WikiProject Military history/Awards',
# 'WikiChevrons with Oak Leaves' => 'Wikipedia:WikiProject Military history/Awards/OAK',
'A-Class medal' => 'Wikipedia:WikiProject Military history/Awards/ACM',
'A-Class medal with Oak Leaves' => 'Wikipedia:WikiProject Military history/Awards/ACM',
'A-Class medal with Swords' => 'Wikipedia:WikiProject Military history/Awards/ACM',
'A-Class medal with Diamonds' => 'Wikipedia:WikiProject Military history/Awards/ACM',
'A-Class cross' => 'Wikipedia:WikiProject Military history/Awards/ACC',
'A-Class cross with Oak Leaves' => 'Wikipedia:WikiProject Military history/Awards/ACC',
'A-Class cross with Swords' => 'Wikipedia:WikiProject Military history/Awards/ACC',
'A-Class cross with Diamonds' => 'Wikipedia:WikiProject Military history/Awards/ACC',
};
my $awards_page = $award_pages->{$award->{award}} or
$cred->error ("Unable to find award '$award->{award}'");
$awards_page = 'User:Hawkeye7/Sandbox6' if $debug;
my $awards_text = $editor->get_text ($awards_page) or
error_exit ("Unable to find '$awards_page')");
$cred->error ("no bots allowed on '$nominations_page'") unless $cred->allow_bots ($awards_text);
if ($award->{award} =~ /A-Class/) {
my @output;
my $added = 0;
my $blank_lines = 0;
my $found_section = 0;
my @award_lines = split /\n/, $awards_text;
foreach my $award_line (@award_lines) {
if (! $added) {
if ($found_section) {
if ($award_line eq '') {
if ($blank_lines) {
push @output, entry ($award);
$added = 1;
} else {
$blank_lines = 1;
}
} elsif ($award_line =~ /User:(.+?)\|/) {
if ($1 gt $award->{nominee}) {
push @output, entry ($award);
$added = 1;
}
}
} elsif ($award_line =~ /The ''$award->{award}'' was introduced/) {
$found_section = 1;
}
}
push @output, $award_line;
}
$awards_text = join "\n", @output;
}
$cred->showtime ("\tAdding award to $awards_page\n");
$editor->edit ({
page => $awards_page,
text => $awards_text,
summary => "Awarded $award->{award} to $award->{nominee}",
minor => 0,
}) or
error_exit ("unable to edit '$awards_page'");
}
sub add_to_bugle ($) {
my $award = shift;
my $bugle_template = join "\n",
"{{Wikipedia:WikiProject Military history/News/$month/Header}}",
'__NOTOC__',
'{{WPMILHIST Newsletter section header 2|From the editors}}',
'{| style="float: right; margin-left: 1em; margin-bottom: 1em; background: transparent;',
'|- style="vertical-align:top;text-align: center;"',
'| [[File:US-O11 insignia.svg|40x40px]] [[File:US-O12 insignia.svg|40x40px]]<br/>[[File:Milhist coordinator emeritus.svg|40x40px]]',
'|}',
'',
'{{WPMILHIST Newsletter section header 2|Awards and honours}}',
'',
'{{WPMILHIST Newsletter section header 2|Contest department}}',
'{| style="float: right; margin-left: 1em; margin-bottom: 1em; background: transparent;"',
'|- style="vertical-align:top;text-align: center;"',
"| [[Image:WikiChevrons.png|40x40px]]\ [[Image:Writer's barnstar.png|40x40px]]",
'|}',
'',
"{{Wikipedia:WikiProject Military history/News/$month/Footer}}";
my $bugle_award_text = {
'A-Class medal' => "[[Image:WPMH ACR.PNG||40x40px|right]]\n*The [[Wikipedia:WikiProject_Military_history/Awards#A-Class_medals|''A-Class medal'']]",
'A-Class medal with Oak Leaves' => "[[Image:WPMH ACR (Oak Leaves).png||40x40px|right]]\n*The [[Wikipedia:WikiProject_Military_history/Awards#A-Class_medals|''A-Class medal with Oak Leaves'']]",
'A-Class medal with Swords' => "[[Image:WPMH ACR (Swords).png||40x40px|right]]\n*The [[Wikipedia:WikiProject_Military_history/Awards#A-Class_medals|''A-Class medal with Swords'']]",
'A-Class medal with Diamonds' => "[[Image:WPMH ACR (Diamonds).png||40x40px|right]]\n*The [[Wikipedia:WikiProject_Military_history/Awards#A-Class_medals|''A-Class medal with Diamonds'']]",
'A-Class cross' => "[[Image:WPMH ACR.PNG||40x40px|right]]\n*The [[Wikipedia:WikiProject_Military_history/Awards#A-Class_crosses|''A-Class cross'']]",
'A-Class cross with Oak Leaves' => "[[Image:WPMH ACR (Oak Leaves).png||40x40px|right]]\n*The [[Wikipedia:WikiProject_Military_history/Awards#A-Class_crosses|''A-Class cross with Oak Leaves'']]",
'A-Class cross with Swords' => "[[Image:WPMH ACR (Swords).png||40x40px|right]]\n*The [[Wikipedia:WikiProject_Military_history/Awards#A-Class_crosses|''A-Class cross with Swords'']]",
'A-Class cross with Diamonds' => "[[Image:WPMH ACR (Diamonds).png||40x40px|right]]\n*The [[Wikipedia:WikiProject_Military_history/Awards#A-Class_crosses|''A-Class cross with Diamonds'']]",
};
my $bugle_text = $editor->get_text ($bugle_page) // $bugle_template;
my $award_text = $bugle_award_text->{$award->{award}} or
$cred->error ("no bugle text for '$award->{award}'");
if ($bugle_text !~ /$award->{award}''\]\] has been awarded to:/) {
$bugle_text =~ s/({{WPMILHIST Newsletter section header 2\|Awards and honours}})/$1\n$award_text has been awarded to:\n/ or
$cred->error ("unable to add section for '$award->{award}'");
}
$bugle_text =~ s/($award->{award}''\]\] has been awarded to:)/$1\n** $award->{nominee} for $award->{citation}./ or
$cred->error ("unable to add citation for '$award->{award}'");
$cred->showtime ("\tAdding award to $bugle_page\n");
$editor->edit ({
page => $bugle_page,
text => $bugle_text,
summary => "Awarded $award->{award} to $award->{nominee}",
minor => 0,
}) or
error_exit ("unable to edit '$bugle_page'");
}
$cred->showtime ("started\n");
my $nominations_text = $editor->get_text ($nominations_page) or
error_exit ("Unable to find '$nominations_page')");
$cred->error ("no bots allowed on '$nominations_page'") unless $cred->allow_bots ($nominations_text);
my @lines = split /\n/, $nominations_text;
my @nominations = grep { /WPMILHIST Award nomination/ } @lines;
foreach my $nomination (@nominations) {
my $award = parse_template ($nomination);
if ($award->{status} eq 'approved') {
$cred->showtime ("Found award for $award->{nominee}\n");
notify_recipient ($award);
add_to_historical_list ($award);
add_to_bugle ($award);
my $updated = $nomination;
$updated =~ s/approved/awarded |diff=$award->{diff} |oldid=$award->{oldid}/;
$nominations_text =~ s/\Q$nomination\E/$updated/;
$cred->showtime ("\tUpdating nomination\n");
$editor->edit ({
page => $nominations_page,
text => $nominations_text,
summary => "Awarded $award->{award} to $award->{nominee}",
minor => 0,
}) or
error_exit ("unable to edit '$nominations_page'");
}
}
$cred->showtime ("finished okay\n");
exit 0;