Approved 2012-03-21 Wikipedia:Bots/Requests for approval/AnomieBOT 61 |
package tasks::ShowByDateSubster;
=pod
=begin metadata
Bot: AnomieBOT
Task: ShowByDateSubster
BRFA: Wikipedia:Bots/Requests for approval/AnomieBOT 61
Status: Approved 2012-03-21
Created: 2012-03-08
Replace expired instances of {{tl|show by date}} with the "after" text. Should an instance need to be not substed, use {{para|nosubst|yes}} or {{para|demo|yes}}.
=end metadata
=cut
use utf8;
use strict;
use Data::Dumper;
use AnomieBOT::Task qw/onlylist timegm/;
use vars qw/@ISA/;
@ISA=qw/AnomieBOT::Task/;
# List of pages to skip
my %skip=(
'Template:Show by date' => 1,
'Template:Show by date/doc' => 1,
'Template:Show by date/testcases' => 1,
'Template:Show by date/sandbox' => 1,
);
# List the rev_id of each template in %repl. If the template on-wiki doesn't
# match, the bot will not touch the template. This prevents it from making the
# wrong replacement if someone changes the template code.
my %goodrevisions=(
'Template:Show by date' => 1252081713,
);
# Replacement functions: return the page to check if it exists and the
# replacement wikitext.
my %repl=(
'Template:Show by date' => sub {
my %p=%{$_[0]};
my $t=time;
my @t=gmtime $t;
my $y=$p{'1'} // ''; $y=($t[5]+1900) if $y eq '';
my $m=$p{'2'} // ''; $m=($t[4]+1) if $m eq '';
my $d=$p{'3'} // ''; $d=$t[3] if $d eq '';
my $h=$p{'hour'} // ''; $h=0 if $h eq '';
my $d2=$p{'delay'} // 0; $d2=0 if $d2 eq '';
return undef unless "$y-$m-$d-$d2-$h"=~/^\d+-\d+-\d+-\d+-\d+$/;
my $tt=timegm(0,0,$h,$d+$d2,$m-1,$y-1900);
return undef if $tt>$t;
return $p{'5'}//'';
},
);
# Iterator definitions
my @iterators=(
{
list => 'embeddedin',
eititle => ['Template:Show by date'],
eilimit => '100',
},
);
sub new {
my $class=shift;
my $self=$class->SUPER::new();
$self->{'iter'}=undef;
$self->{'iterators'}=[@iterators];
bless $self, $class;
return $self;
}
=pod
=for info
Approved 2012-03-21<br />[[Wikipedia:Bots/Requests for approval/AnomieBOT 61]]
=cut
sub approved {
return 3;
}
sub run {
my ($self, $api)=@_;
my $res;
$api->task('ShowByDateSubster',0,10,qw/d::Redirects d::Templates d::Talk/);
# Check if the templates are still known-good versions
$res=$api->query(titles=>join('|',keys %goodrevisions), prop=>'info');
if($res->{'code'} ne 'success'){
$api->warn("Failed to check template revisions: ".$res->{'error'}."\n");
return 60;
}
my %r=map { $_->{'title'},$_ } values %{$res->{'query'}{'pages'}};
while(my ($k,$v)=each %repl){
next if(defined($r{$k}) && !defined($goodrevisions{$k}));
next if(defined($r{$k}) && $r{$k}{'lastrevid'}==$goodrevisions{$k});
my $r=$api->whine("[[$k]] was modified!", "The template [[$k]] was modified from the last known good version ({{diff|page=$k|diff=cur|oldid=".$goodrevisions{$k}."|label=diff}}). Please check that my replacement function for that template is still correct, and then update the good revision id to the current revision.");
if($r->{'code'} ne 'success'){
$api->warn("Whine failed: ".$r->{'error'}."\n");
return 60;
}
delete $repl{$k};
}
return undef unless %repl;
# Get a list of templates redirecting to our targets
my %templates=$api->redirects_to_resolved(keys %repl);
if(exists($templates{''})){
$api->warn("Failed to get redirects to target templates: ".$templates{''}{'error'}."\n");
return 60;
}
my ($k,$v);
$templates{$k}=$repl{$v} while(($k,$v)=each %templates);
# Spend a max of 5 minutes on this task before restarting
my $endtime=time()+300;
while(1){
my $iter=$self->{'iter'};
if(!defined($iter)){
my $i=shift @{$self->{'iterators'}};
last unless $i;
$iter=$api->iterator(%$i);
$self->{'iter'}=$iter;
}
while($_=$iter->next){
if(!$_->{'_ok_'}){
$api->warn("Failed to retrieve pages: ".$_->{'error'}."\n");
return 60;
}
next if exists($skip{$_->{'title'}});
my $title=$_->{'title'};
$api->log("Checking for templates in $title");
# WTF?
if(exists($_->{'missing'})){
$api->warn("$title is missing? WTF?\n");
next;
}
# Ok, check the page
my $tok=$api->edittoken($title, EditRedir=>1);
if($tok->{'code'} eq 'shutoff'){
$api->warn("Task disabled: ".$tok->{'content'}."\n");
return 300;
}
if($tok->{'code'} ne 'success'){
$api->warn("Failed to get edit token for $title: ".$tok->{'error'}."\n");
next;
}
next if exists($tok->{'missing'});
# Get page text
my $intxt=$tok->{'revisions'}[0]{'slots'}{'main'}{'*'};
# Perform the actual replacements
my %r=();
my $paranoia=0;
my $outtxt=$api->process_templates($intxt, sub {
my $name=shift;
my $params=shift;
my $wikitext=shift;
return undef unless exists($templates{"Template:$name"});
my %p=();
foreach ($api->process_paramlist(@$params)){
$p{$_->{'name'}}=$_->{'value'};
}
return undef if(exists($p{'demo'}) || exists($p{'nosubst'}));
my $rp=$templates{"Template:$name"}(\%p, $params, $wikitext);
return undef unless defined($rp);
$r{$name}=1;
$paranoia=1 if $rp eq '';
return $rp;
});
# Need to edit?
if($outtxt ne $intxt){
my $summary="Replacing/removing expired templates: {{".join("}} {{", keys %r)."}}";
$summary.=' (please review this edit)' if $paranoia;
$api->log("$summary in $title");
my $r=$api->edit($tok, $outtxt, $summary, !$paranoia, !$paranoia);
if($r->{'code'} ne 'success'){
$api->warn("Write failed on $title: ".$r->{'error'}."\n");
next;
}
} else {
$api->log("Nothing to do in $title");
}
# If we've been at it long enough, let another task have a go.
return 0 if time()>=$endtime;
}
$self->{'iter'}=undef;
}
# No more pages to check for now
$self->{'iter'}=undef;
$self->{'iterators'}=[@iterators];
return 21600;
}
1;