User:FACBot/fac.pl

{{syntaxhighlight|lang=perl|code=

  1. !/usr/bin/perl -w
  2. fac.pl -- Pass or fail an Featured Article class review
  3. This Bot runs every day, looking for featured class articles that have been promoted by a delegate
  4. If it finds one, it follows the steps involved in promoting or failing it.
  5. Usage: fac.pl
  6. 21 Sep 14 Created
  7. 2 Sep 17 Correction for new announcements page format
  8. 9 Sep 17 Fix for GA templates missing oldids
  9. 15 Nov 17 Guard against not being able to find nomination page
  10. 23 Feb 18 allow bots moved to cred; some code for old articles with GA reviews on the talk page
  11. 26 Apr 18 Fix for .. tags on archive page

use English;

use strict;

use utf8;

use warnings;

use Carp;

use Data::Dumper;

use Date::Calc qw(Delta_Days);

use Date::Parse;

use DateTime;

use File::Basename qw(dirname);

use File::Spec;

use MediaWiki::Bot;

use POSIX qw(strftime);

use XML::Simple;

binmode (STDERR, ':utf8');

binmode (STDOUT, ':utf8');

  1. Pages used

my $candidates_page = 'Wikipedia:featured article candidates';

my $encoded_nomination;

my $announcements = 'Template:Announcements/New featured content';

my $goings_on = 'Wikipedia:Goings-on';

my $showcase_a = 'Wikipedia:WikiProject Military history/Showcase/A';

my $showcase_fa = 'Wikipedia:WikiProject Military history/Showcase/FA';

my @months = qw(January February March April May June July August September October November December);

my $editor = MediaWiki::Bot->new ({

assert => 'bot',

host => 'en.wikipedia.org',

protocol => 'https',

operator => 'Hawkeye7',

}) or die "new MediaWiki::Bot failed";

my $dirname = dirname (__FILE__, '.pl');

push @INC, $dirname;

require Cred;

my $cred = new Cred ();

my $log = $cred->log ();

require showcase;

sub error_exit ($) {

my @message = @ARG;

if ($editor->{error}->{code}) {

push @message, ' (', $editor->{error}->{code} , ') : ' , $editor->{error}->{details};

}

$cred->error (@message);

}

sub has_been_closed ($) {

my ($nomination) = @ARG;

$cred->showtime ("checking if $nomination has been closed...\n");

my $text = $editor->get_text ($nomination) or do {

$cred->showtime ("Unable to find nomination page '$nomination')\n");

return ();

};

if ($text =~ /{{FACClosed.+ (\d+:\d+, (\d+) (\w+) (\d+))/) {

$cred->showtime ("$nomination has been closed\n");

return ($1, $2, $3, $4);

}

return ();

}

sub has_been_promoted ($$$) {

my ($nomination, $month, $year) = @ARG;

$cred->showtime ("\tchecking if $nomination has been promoted...\n");

my $log_page = "Wikipedia:Featured article candidates/Featured log/$month $year";

my $log_text = $editor->get_text ($log_page) or

error_exit ("Unable to find '$log_page')");

$log_text =~ s/_/ /g;

if ($log_text =~ /\Q$nomination\E/) {

$cred->showtime ("\tfound $nomination\n");

return 1;

}

$cred->showtime ("\t$nomination NOT promoted\n");

return 0;

}

sub has_been_archived ($$$) {

my ($nomination, $month, $year) = @ARG;

$cred->showtime ("checking if $nomination has been archived...\n");

my $log_page = "Wikipedia:Featured article candidates/Archived nominations/$month $year";

my $log_text = $editor->get_text ($log_page) or

error_exit ("Unable to find '$log_page')");

$log_text =~ s/_/ /g;

if ($log_text =~ /\Q$nomination\E/) {

$cred->showtime ("\tfound $nomination\n");

return 1;

}

$cred->showtime ("\t$nomination NOT archived\n");

return 0;

}

sub whodunnit ($$$) {

my ($article, $nomination, $action) = @ARG;

my $old;

my @history = $editor->get_history ($nomination) or

error_exit ("Unable to get history of '$nomination'");

foreach my $revision (@history) {

  1. print Dumper $revision, "\n";

my $text = $editor->get_text ($nomination, $revision->{revid}) or

error_exit ("Unable to find '$nomination:$revision->{revid}')");

if ($text !~ /{{FACClosed/) {

$cred->showtime ("\t$article was $action by $old->{user} at $old->{timestamp_date} $old->{timestamp_time}\n");

my $diff = "https://en.wikipedia.org/w/index.php?title=$nomination\&diff=$old->{revid}\&oldid=$revision->{revid}";

$diff =~ s/ /_/g;

  1. print $diff, "\n";

return ($old->{user}, $old->{timestamp_date}, $old->{timestamp_time}, $diff);

} else {

$old = $revision;

}

}

}

sub remove_from_candidates ($$) {

my ($page, $nomination) = @ARG;

$cred->showtime ("\tRemoving from the candidates page\n");

my $candidates_text = $editor->get_text ($candidates_page) or

error_exit ("Unable to find '$candidates_page')");

$candidates_text =~ s/{{$nomination}}//;

$editor->edit ({

page => $candidates_page,

text => $candidates_text,

summary => "Removing $page from FAC candidates page",

bot => 1,

minor => 0,

}) or

error_exit ("unable to edit '$candidates_page'");

}

sub promote_update_nomination_page ($$$$$) {

my ($page, $nomination, $user, $date, $diff) = @ARG;

$cred->showtime ("\tUpdating the nomination page\n");

my $text = $editor->get_text ($nomination) or

error_exit ("Unable to find '$nomination')");

# Remove transcluded article links and featured article tools

$text =~ s/.+?<\/noinclude>//s;

# Tag the top and bottom of the page

my $result = "promoted by $user via ~~~ $date [$diff]";

my $top = "{{subst:Fa top|result=$result}}";

my $bottom = "{{subst:Fa bottom}}\n";

$text = join "\n", $top, $text, $bottom;

$editor->edit ({

page => $nomination,

text => $text,

summary => "Promoting '$page'",

bot => 1,

minor => 0,

}) or

error_exit ("unable to edit '$nomination'");

}

sub archive_update_nomination_page ($$$$$) {

my ($page, $nomination, $user, $date, $diff) = @ARG;

$cred->showtime ("\tUpdating the nomination page\n");

my $text = $editor->get_text ($nomination) or

error_exit ("Unable to find '$nomination')");

# Remove transcluded article links and featured article tools

$text =~ s/.+?<\/noinclude>//s;

# Tag the top and bottom of the page

my $result = "archived by $user via ~~~ $date [$diff]";

my $top = "{{subst:Fa top|result=$result}}";

my $bottom = "{{subst:Fa bottom}}\n";

$text = join "\n", $top, $text, $bottom;

$editor->edit ({

page => $nomination,

text => $text,

summary => "Archiving '$page'",

bot => 1,

minor => 0,

}) or

error_exit ("unable to edit '$nomination'");

}

sub good_article_lists () {

$cred->showtime ("\tFinding the good article lists\n");

my $good_articles = 'Wikipedia:Good articles';

my $good_articles_all = "$good_articles/all";

my $text = $editor->get_text ($good_articles_all) or

error_exit ("Unable to find '$good_articles_all'");

$cred->error ("no bots allowed on '$good_articles_all'") unless $cred->allow_bots ($text);

my @good_article_lists = $text =~ /{{($good_articles\/[A-Z].+)}}/g;

  1. foreach (@good_article_lists) {
  2. print $ARG, "\n";
  3. }

return @good_article_lists;

}

sub update_good_article_list ($) {

my ($article) = @ARG;

$cred->showtime ("\tFinding $article in the good article list\n");

my @good_article_lists = good_article_lists ();

my $foundit = 0;

my $totals_updated = 0;

foreach my $list (@good_article_lists) {

my $text = $editor->get_text ($list) or

error_exit ("Unable to find '$list'");

$cred->error ("no bots allowed on '$list'") unless $cred->allow_bots ($text);

my @input = split /\n/, $text;

my @output;

foreach (@input) {

if (! $foundit) {

if (/\[\[([^\]\|]+)/) {

my $good_article_name = $1;

  1. print $good_article_name, "\n";

if ($good_article_name eq $article) {

$foundit = 1;

next;

}

}

}

if ($foundit && ! $totals_updated) {

if (/\((\d+) articles\)/) {

  1. print $ARG, "\n";

my $updated = $1 - 1;

s/$1/$updated/;

$totals_updated = 1;

  1. print $ARG, "\n";

}

}

push @output, $ARG;

}

if ($foundit) {

$text = join "\n", @output;

last;

$editor->edit ({

page => $list,

text => $text,

summary => 'update good article list',

minor => 0,

}) or

error_exit ("unable to edit '$list'");

last;

}

last;

}

}

sub promote_update_article_page ($) {

my ($page) = @ARG;

$cred->showtime ("\tUpdating the article page\n");

my $text = $editor->get_text ($page) or

error_exit ("Unable to find '$page')");

if ($text =~ s/{{good article}}//i) {

update_good_article_list ($page);

}

$text =~ s/^/{{featured article}}\n/;

$editor->edit ({

page => $page,

text => $text,

summary => "Promoting '$page' to Featured Article status",

bot => 1,

minor => 0,

}) or

error_exit ("unable to edit '$page'");

}

sub remove_from_ga ($) {

my ($page) = @ARG;

$cred->showtime ("\tRemoving from GA...\n");

my $all = 'Wikipedia:Good articles/all';

my $text = $editor->get_text ($all) or

error_exit ("Unable to find '$all')");

my @categories = $text =~/{{(Wikipedia:Good articles\/[\w\s]+?)}}/g;

foreach my $category (@categories) {

  1. print $category, "\n";

$text = $editor->get_text ($category) or

error_exit ("Unable to find '$category')");

$cred->error ("no bots allowed on '$category'") unless $cred->allow_bots ($text);

if ($text =~ /\Q$page\E/) {

$cred->showtime ("\t\tfound $page in $category\n");

my @a;

my $decrement_count = 0;

my @lines = split /\n/, $text;

foreach (@lines) {

if (/\Q$page\E/) {

$decrement_count = 1;

next;

}

if ($decrement_count && /(\d+) articles/) {

$decrement_count = 0;

my $count = $1 - 1;

s/\d+/$count/;

}

push @a, $ARG;

}

$text = join "\n", @a, "\n";

$editor->edit ({

page => $category,

text => $text,

summary => "$page has been promoted to Featured Article status",

bot => 1,

minor => 0,

}) or

error_exit ("unable to edit '$category'");

return;

}

}

}

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 ($p =~ /^(\w+)\s*=/) {

next;

}

if (!defined $p{$arg}) {

$p{$arg} = $p;

next param;

}

}

}

  1. foreach my $p (keys %p) {
  2. print "$p => $p{$p}\n";
  3. }

return %p;

}

sub newaction ($$$$$$) {

my ($action, $date, $link, $result, $revid, $id) = @ARG;

my $newaction = join "\n",

"|action${id}=$action",

"|action${id}date=$date",

"|action${id}link=$link",

"|action${id}result=$result",

"|action${id}oldid=$revid";

return $newaction;

}

sub has_nested_text ($\$) {

my ($tag, $text) = @ARG;

  1. print "tag='$tag'\n";

my $has_nested_text = 0;

while ($$text =~ /{{$tag[^}]+({{[^}]+}})/) {

  1. print "Nested text!!!!\n";

my $nested_text = $1;

  1. print "nested text='$nested_text'\n";

my $transformed_text = $nested_text;

$transformed_text =~ s/{{(.+)}}/%%<$1>%%/;

  1. print "transformed text=$transformed_text\n";

$$text =~ s/\Q$nested_text\E/$transformed_text/;

$has_nested_text = 1;

}

return $has_nested_text;

}

sub reset_nested_text (\$) {

my ($text) = @ARG;

$$text =~ s/%%

$$text =~ s/>%%/}}/g;

}

sub update_article_history ($$$$$$) {

my ($text, $action, $date, $link, $result, $revid) = @ARG;

$text =~ s/{{Article\s*History/{{ArticleHistory/is;

my ($articleHistory) = $text =~ /{{ArticleHistory(.+)}}/gis;

if ($articleHistory) {

  1. print "update article history\n";

my $has_nested_text = has_nested_text ('ArticleHistory', $text);

  1. print "articlehistory='$articleHistory'\n";

for (my $id = 1;; ++$id) {

if ($articleHistory =~ /action$id/) {

  1. print "\t\tfound action$id\n";

} else {

  1. print "\t\tno $id - going with that\n";

my $newaction = newaction ($action, $date, $link, $result, $revid, $id);

$text =~ s/{{ArticleHistory(.+?)}}/{{ArticleHistory$1\n$newaction\n}}/is;

last;

}

}

if ($has_nested_text) {

reset_nested_text ($text);

}

} else {

my $newaction = newaction ($action, $date, $link, $result, $revid, 1);

$text =~ s/^/{{ArticleHistory\n$newaction\n}}\n/is;

}

return $text;

}

sub get_revid ($$$) {

my ($page, $date, $time) = @ARG;

my @history = $editor->get_history ($page) or

error_exit ("Unable to get history of '$page'");

foreach my $history (@history) {

if ("$history->{timestamp_date} $history->{timestamp_time}" le "$date $time") {

return $history->{revid};

}

}

error_exit ("Unable to get revid of '$page')");

}

sub parse_display_date ($) {

my ($display_date) = @ARG;

my ($ss, $mm, $hh, $day, $month, $year, $zone) = strptime ($display_date) or

error_exit ("Unable to parse date '$display_date'");

my $dt = DateTime->new (

year => 1900 + $year,

month => 1 + $month,

day => $day,

hour => $hh // 0,

minute => $mm // 0,

second => $ss // 0,

);

my $date = $dt->strftime ("%Y-%m-%d");

my $time = $dt->strftime ("%H:%M");

return ($time, $date);

}

sub add_ga_to_history ($$$) {

my ($article, $text, $talk) = @ARG;

if ($text =~ s/{{GA[^m](.+?)}}//is) {

my %h = parse_template ($1, 'date', 'oldid', 'page', 'topic');

my $revid = $h{oldid};

my $display_date = $h{date};

my $gaid = $h{page} // 1;

my $link = "$talk/GA$gaid";

if (!defined $revid || $revid !~ /\d+/) {

my ($time, $date) = parse_display_date ($display_date);

$revid = get_revid ($article, $date, $time);

}

$text = update_article_history ($text, 'GAN', $display_date, $link, 'listed', $revid);

}

return $text;

}

sub add_pr_to_history ($$) {

my ($page, $text) = @ARG;

$cred->showtime ("\tFound old Peer Review\n");

while ($text =~ s/{{oldpeerreview(.+?)}}//is) {

my %h = parse_template ($1, 'name', 'archive');

my $name = $h{name} // $page;

my $archive = defined $h{archive} ? "/archive$h{archive}" : '';

my $link = "Wikipedia:Peer_review/$name$archive";

my ($history) = $editor->get_history ($link) or

error_exit ("Unable to get history of '$link'");

my $date = $history->{timestamp_date};

my $time = $history->{timestamp_time};

my $revid = get_revid ($page, $date, $time);

$text = update_article_history ($text, 'PR', $date, $link, 'reviewed ', $revid);

}

return $text;

}

sub promote_update_talk_page ($$$$$) {

my ($page, $talk, $nomination_page, $date, $time) = @ARG;

$cred->showtime ("\tUpdating the talk page\n");

my $text = $editor->get_text ($talk) or

error_exit ("Unable to find '$talk')");

# Remove the candidacy

$text =~ s/{{featured article candidates\|.+?}}//;

# Remove from GA

if ($text =~ /{{GA[^L].+?}}/gis) { # NOT GAList - from some really old talk pages that include the GA assessment

if ($text !~ /{{GA Nominee/i) { # Happens when a GA Nominee is nominated for FAC

$text = add_ga_to_history ($page, $text, $talk);

remove_from_ga ($page);

}

} elsif ($text =~ /currentstatus=GA/gi || $text =~ /class=GA/gi) {

remove_from_ga ($page);

}

# add an old Peer review, if any, to the article history

if ($text =~ /{{oldpeerreview.+?}}/gis) {

$text = add_pr_to_history ($page, $text);

}

# Update the article history

my $revid = get_revid ($page, $date, $time);

$text = update_article_history ($text, 'FAC', $date, $nomination_page, 'promoted', $revid);

unless ($text =~ s/currentstatus\s*=\s*\w+/currentstatus=FA/is) {

$text =~ s/{{Article\s*History/{{ArticleHistory\n|currentstatus=FA\n/is;

}

# Add DYK, if any, to the article history

my $tag;

if ($text =~ /\{\{(DYK talk|dyktalk)/) {

$tag = $1;

}

if ($tag) {

my $has_nested_text = has_nested_text ($tag, $text);

if ($text =~ s/{{$tag\|(.+?)\|(\d+)\|entry=(.+?)}}//is) {

  1. print "\tFound DYK\n";

my $dykdate="$1 $2";

my $dykentry = $3;

$text =~ s/currentstatus=FA/currentstatus=FA\n\n|dykdate=$dykdate\n|dykentry=$dykentry/is;

}

if ($has_nested_text) {

reset_nested_text ($text);

}

}

# Update the class for all projects

$text =~ s/([^-]class)\s*=\s*(\w+)/$1=FA/igs;

$editor->edit ({

page => $talk,

text => $text,

summary => "Promoting '$page' to Featured Article status",

bot => 1,

minor => 0,

}) or

error_exit ("unable to edit '$talk'");

}

sub archive_update_talk_page ($$$$$) {

my ($page, $talk, $nomination_page, $date, $time) = @ARG;

$cred->showtime ("\tUpdating the talk page\n");

my $text = $editor->get_text ($talk) or

error_exit ("Unable to find '$talk')");

# Remove the candidacy

$text =~ s/{{featured article candidates\|.+?}}//;

# Add the GA review, if any, to the article history

if ($text =~ /{{GA[^L].+?}}/gis) {

$text = add_ga_to_history ($page, $text, $talk);

}

# add an old Peer review, if any, to the article history

if ($text =~ /{{oldpeerreview.+?}}/gis) {

$text = add_pr_to_history ($page, $text);

}

# Update the article history

my $revid = get_revid ($page, $date, $time);

$text = update_article_history ($text, 'FAC', $date, $nomination_page, 'failed', $revid);

# Update the current status

unless ($text =~ /currentstatus\s*=\s*.+/is) {

if ($text =~ /class\s*=\s*GA/is) {

$text =~ s/{{Article\s*History/{{ArticleHistory\n|currentstatus=GA\n/is;

}

}

# Add DYK, if any, to the article history

my $tag;

if ($text =~ /\{\{(DYK talk|dyktalk)/) {

$tag = $1;

}

if ($tag) {

my $has_nested_text = has_nested_text ($tag, $text);

if ($text =~ s/{{$tag\|(.+?)\|(\d+)\|entry=(.+?)}}//is) {

  1. print "\tFound DYK\n";

my $dykdate="$1 $2";

my $dykentry = $3;

$text =~ s/currentstatus=FA/currentstatus=FA\n\n|dykdate=$dykdate\n|dykentry=$dykentry/is;

}

if ($has_nested_text) {

reset_nested_text ($text);

}

}

$editor->edit ({

page => $talk,

text => $text,

summary => "Updating '$page' after unsuccessful Featured Article nomination",

bot => 1,

minor => 0,

}) or

error_exit ("unable to edit '$talk'");

}

  1. Find the nomination page

sub nomination ($) {

my ($talk) = @ARG;

my $text = $editor->get_text ($talk) or

error_exit ("Unable to find '$talk')");

$text =~ /{{featured article candidates\|(.+?\/archive\d+)/;

error_exit ("Unable to find featured article candidates template in '$talk'") unless $1;

my $nomination = "Wikipedia:Featured article candidates/$1";

$encoded_nomination = $nomination;

$nomination =~ s/&#([0-9a-f]+);/chr($1)/ige;

$cred->showtime ("\t$nomination\n");

return $nomination;

}

sub update_announcements_page ($) {

$cred->showtime ("\tUpdating the announcements page\n");

my ($article) = @ARG;

my $text = $editor->get_text ($announcements) or

error_exit ("Unable to find '$announcements'");

$cred->error ("no bots allowed on '$announcements'") unless $cred->allow_bots ($text);

if ($text =~ /\Q$article\E/) {

$cred->showtime ("\t\tAlready updated -- skipping\n");

return;

}

my $in_list_section = 0;

my $section_max;

my @input_lines = split /\n/, $text;

my @output_lines;

foreach (@input_lines) {

if (//) {

$section_max = $1;

$in_list_section++;

my $a = $article;

push @output_lines, $ARG, "* $article";

next;

}

if ($in_list_section) {

if (/^$|<\/div>|/) {

$in_list_section = 0;

} elsif ($in_list_section < $section_max) {

$in_list_section++;

} else {

next;

}

}

push @output_lines, $ARG;

}

$text = join "\n", @output_lines;

$editor->edit ({

page => $announcements,

text => $text,

summary => "$article promoted to Featured Article status",

minor => 0,

}) or

error_exit ("unable to edit '$announcements'");

}

sub text_to_month ($) {

my ($month) = @ARG;

for my $i (0..11) {

if ($months[$i] eq $month) {

return $i + 1;

}

}

}

sub update_goings_on_page ($$) {

$cred->showtime ("\tUpdating the goings_on page\n");

my ($article, $timestamp) = @ARG;

my $text = $editor->get_text ($goings_on) or

error_exit ("Unable to find '$goings_on'");

$cred->error ("no bots allowed on '$goings_on'") unless $cred->allow_bots ($text);

my ($m, $d, $y) = $text =~ /week starting Sunday, \[\[(\w+) (\d+)\]\], \[\[(\d+)\]\]/;

  1. print "$d $m $y\n";

my $delta_days = Delta_Days ($y, text_to_month ($m), $d, $timestamp->{YEAR}, text_to_month ($timestamp ->{MONTH}) ,$timestamp->{DAY});

  1. print "delta days=$delta_days\n"; # Normally positive

if ($delta_days < 0) {

$cred->showtime ("\t\tArticle dated $timestamp->{DAY} $timestamp->{MONTH} $timestamp->{YEAR} but page is $d $m $y -- skipping\n");

return;

}

if ($text =~ /\Q$article\E/) {

$cred->showtime ("\t\tAlready updated -- skipping\n");

return;

}

my $abbr = substr ($timestamp->{MONTH}, 0, 3);

my $day = $timestamp->{DAY};

$day =~ s/^0//;

my $date = "$day $abbr";

my $in_list_section = 0;

my @input_lines = split /\n/, $text;

my @output_lines;

foreach (@input_lines) {

if (/Wikipedia:Featured articles/) {

$in_list_section = 1;

}

if ($in_list_section) {

if (/^$|Wikipedia:Featured lists/) {

$in_list_section = 0;

push @output_lines, "* $article ($date)";

}

}

push @output_lines, $ARG;

}

$text = join "\n", @output_lines;

$editor->edit ({

page => $goings_on,

text => $text,

summary => "$article promoted to Featured Article status",

minor => 0,

}) or

error_exit ("unable to edit '$goings_on'");

}

sub add_to_showcase ($) {

my ($article) = @ARG;

my $showcase_text = $editor->get_text ($showcase_fa) or

error_exit ("Unable to find '$showcase_fa'");

$cred->error ("no bots allowed on '$showcase_fa'") unless $cred->allow_bots ($showcase_text);

my $showcase = new showcase ($showcase_text);

$showcase->add ($article);

$editor->edit ({

page => $showcase_fa,

text => $showcase->text,

summary => "'$article' has been promoted to Featured Article status",

  1. bot => 1,

minor => 0,

}) or

error_exit ("unable to edit '$showcase_fa'");

}

sub remove_from_showcase ($) {

my ($article) = @ARG;

my $showcase_text = $editor->get_text ($showcase_a) or

error_exit ("Unable to find '$showcase_a'");

$cred->error ("no bots allowed on '$showcase_a'") unless $cred->allow_bots ($showcase_text);

my $showcase = new showcase ($showcase_text);

my $found = $showcase->del ($article);

if ($found) {

$editor->edit ({

page => $showcase_a,

text => $showcase->text,

summary => "'$article' has been promoted to Featured Article status",

  1. bot => 1,

minor => 0,

}) or

error_exit ("unable to edit '$showcase_a'");

}

return $found;

}

sub is_older_nomination ($$) {

my ($nomination, $twenty_days_ago) = @ARG;

  1. print "$nomination\n";

my @history = $editor->get_history ($nomination) or

error_exit ("Unable to get history of '$nomination'");

my $revision = pop @history;

  1. print "$revision->{timestamp_date}\n";

my $is_older_nomination = $revision->{timestamp_date} lt $twenty_days_ago;

  1. print $is_older_nomination ? "\tis older than twenty_days_ago\n" : "\tis NOT older than twenty_days_ago\n" ;

return $is_older_nomination;

}

sub move_the_daily_marker () {

my $text = $editor->get_text ($candidates_page) or

error_exit ("Unable to find '$candidates_page'");

$cred->error ("no bots allowed on '$candidates_page'") unless $cred->allow_bots ($text);

my @input = split /\n/, $text;

my @output;

my $nominations = 0;

my @older_nominations;

my $older_nominations = 0;

$cred->showtime ("Move the daily marker\n");

my $twenty_days_ago = strftime ('%Y-%m-%d', gmtime(time () - 20 * 24 * 60 * 60));

  1. print "twenty days ago was $twenty_days_ago\n";

foreach (@input) {

if (//) {

}elsif (/==Nominations==/) {

$nominations = 1;

} elsif (/==Older nominations==/) {

$older_nominations = 1;

$nominations = 0;

} elsif ($nominations) {

if (/{{(Wikipedia:Featured article candidates.+)}}/) {

my $nomination = $1;

if (is_older_nomination ($nomination, $twenty_days_ago)) {

push @older_nominations, "{{$nomination}}";

next;

}

}

} elsif ($older_nominations) {

if (@older_nominations) {

push @output, @older_nominations;

$older_nominations = 0;

}

}

push @output, $ARG;

}

unless (@older_nominations) {

$cred->showtime ("No need to reset daily marker\n");

return;

}

$text = join "\n", @output;

$editor->edit ({

page => $candidates_page,

text => $text,

summary => 'update daily marker',

minor => 0,

}) or

error_exit ("unable to edit '$candidates_page'");

$cred->showtime ("Daily marker reset\n");

}

$editor->login ({

username => $cred->user,

password => $cred->password

}) or error_exit ("login failed");

$cred->showtime ("========== Commenced ==========\n");

move_the_daily_marker ();

  1. First, we need to find the nomination pages

my @candidates = $editor->get_pages_in_category ('Wikipedia featured article candidates');

foreach my $talk (@candidates) {

my $article = $talk;

$article =~ s/Talk:// or

next;

my $nomination = nomination ($talk);

if (my ($display_date, $day, $month, $year) = has_been_closed ($nomination)) {

$cred->showtime ("\t$nomination closed on $display_date\n");

if (has_been_promoted ($nomination, $month, $year)) {

my ($user, $date, $time, $diff) = whodunnit ($article, $nomination, 'promoted');

promote_update_talk_page ($article, $talk, $nomination, $date, $time);

promote_update_nomination_page ($article, $nomination, $user, $display_date, $diff);

promote_update_article_page ($article);

update_announcements_page ($article);

update_goings_on_page ($article, {YEAR => $year, MONTH => $month, DAY => $day});

my $found = remove_from_showcase ($article);

add_to_showcase ($article) if $found;

} elsif (has_been_archived ($nomination, $month, $year)) {

my ($user, $date, $time, $diff) = whodunnit ($article, $nomination, 'archived');

archive_update_talk_page ($article, $talk, $nomination, $date, $time);

archive_update_nomination_page ($article, $nomination, $user, $display_date, $diff);

} else {

$cred->showtime ("WARNING: FAC closed but $nomination has NOT been moved to the archive page\n");

}

} else {

$cred->showtime ("\t$nomination is still current\n");

}

}

$cred->showtime ("finished okay\n");

exit 0;

}}