User:MilHistBot/awards.pl

From Wikipedia, the free encyclopedia
#!/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;