Approved 2009-03-07 Wikipedia:Bots/Requests for approval/AnomieBOT 26 |
package tasks::TemplateReplacer15;
=pod
=begin metadata
Bot: AnomieBOT
Task: TemplateReplacer15
BRFA: Wikipedia:Bots/Requests for approval/AnomieBOT 26
Status: Approved 2009-03-07
Created: 2009-01-15
OnDemand: true
Replace all transclusions of one template with another (or with several others
depending on template parameters, etc), when a template must be renamed.
Normally, this will be the result of a TFD, but it could be used for any
clear-cut case. It will ''not'' be done just to replace a template redirect
when the redirect is going to remain.
=end metadata
=cut
use utf8;
use strict;
use Data::Dumper;
use AnomieBOT::Task;
use vars qw/@ISA/;
@ISA=qw/AnomieBOT::Task/;
# Sequence number
my $seq=10;
my $req="[[User:AnomieBOT/req/Template:fact|request]]";
my $errors="Errors or discussion? Post a note [[User:AnomieBOT/shutoff/TemplateReplacer15|here]] to stop the bot.";
my $force=1;
my $unique=1;
# List of templates to remove/replace in this task. Values may be the new
# template name (simple replacement), the empty string (removal), or a function
# ref (something more complicated).
my %repl=(
'Template:Citation needed' => \&repl,
);
my @templates=keys %repl;
# If your function ref above fails for some reason, set this true.
my $fail=0;
sub repl {
my $api=shift;
my $name=shift;
my $params=shift;
my $wikitext=shift;
my $data=shift;
my $oname=shift;
my $found=0;
my $dt='';
my $founddate=0;
my $ret="{{$oname";
my @reason=();
foreach ($api->process_paramlist(@$params)){
if($_->{'name'}=~/^\d+$/){
$found=1;
push @reason, $_->{'value'};
next if $_->{'value'}=~/^\s*$/;
next if $_->{'value'}=~/^\s*date\s*$/i;
if($_->{'value'}=~/^\s*(?:January|February|March|April|May|June|July|August|September|October|November|December) \d\d\d\d\s*$/i){
$_->{'value'}=~s/^\s+|\s+$//g;
$dt=ucfirst(lc($_->{'value'}));
pop @reason;
next;
}
next if $_->{'value'}=~/^\s*\d{4}-\d{2}-\d{2}\s*$/;
$ret.='|reason='.$_->{'value'};
} else {
push @reason, $_->{'value'} if $_->{'name'} eq 'reason';
$founddate=1 if $_->{'name'} eq 'date';
$ret.='|'.$_->{'text'};
}
}
return undef unless $found;
if(@reason>1){
# Multiple named parameters and/or reason=
$ret="{{$oname";
foreach ($api->process_paramlist(@$params)){
if($_->{'name'}=~/^(?:\d+|reason)$/){
next if($_->{'name'} ne 'reason' && $_->{'value'}=~/^\s*(?:January|February|March|April|May|June|July|August|September|October|November|December) \d\d\d\d\s*$/i);
$ret.='|reason='.join(' ',@reason) if @reason;
@reason=();
} else {
$ret.='|'.$_->{'text'};
}
}
}
$ret.="|date=$dt" if(!$founddate && $dt ne '');
$ret.='}}';
return ($ret,"or removing deprecated unnamed parameter use in {{citation needed}}");
};
# List of pages to skip
my %skip=(
# User doesn't care
'User talk:Chzz/Archive 5'=>1,
# Using "tlrow" for example tables, which I think can't work "right" with
# the new parser anyway
'User:Born2flie/Tools'=>1,
'User:Faizhaider/inline'=>1,
'User:Mattisse/inline'=>1,
'User:Rich Farmbrough/temp85'=>1,
'User talk:Ultramarine/Tags'=>1,
'User:Wbfergus/Sandbox'=>1,
'Wikipedia:Template messages/Cleanup'=>1,
'Wikipedia:Template messages/Cleanup/Verifiability and sources'=>1,
'Wikipedia:Template messages/Sources of articles'=>1,
);
# Iterator definitions
my @iter=(
{
list => 'categorymembers',
cmtitle => 'Category:Articles using citation needed template with unnamed parameter',
cmlimit => 'max',
},
);
sub new {
my $class=shift;
my $self=$class->SUPER::new();
bless $self, $class;
return $self;
}
=pod
=for info
Approved 2009-03-07<br />[[Wikipedia:Bots/Requests for approval/AnomieBOT 26]]
=cut
sub approved {
return -1;
}
sub run {
my ($self, $api)=@_;
my $res;
$api->task('TemplateReplacer15',0,10,qw/d::Redirects d::Templates d::WikiProjectTagging/);
# Spend a max of 5 minutes on this task before restarting
my $endtime=time()+300;
# 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);
foreach my $iterdef (@iter){
my $iter=$api->iterator(%$iterdef);
while($_=$iter->next){
if(!$_->{'_ok_'}){
$api->warn("Failed to retrieve transclusion list: ".$_->{'error'}."\n");
return 60;
}
next if exists($skip{$_->{'title'}});
my $pageid=$_->{'pageid'};
next if(!$force && exists($api->store->{$pageid}) && $api->store->{$pageid}>=$seq);
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 removal
my @repl=();
my @remv=();
$fail=0;
my $outtxt=$api->process_templates($intxt, sub {
return undef if $fail;
my $name=shift;
my $params=shift;
my $wikitext=shift;
my $data=shift;
my $oname=shift;
return undef unless exists($templates{"Template:$name"});
my $t=$templates{"Template:$name"};
my ($ret,$log);
if(ref($t) eq 'CODE'){
($ret,$log)=$t->($api, $name, $params, $wikitext, $data, $oname);
return undef if $fail;
return undef unless defined($ret);
} elsif($t eq ''){
($ret,$log)=('','');
} else {
$oname=~s/^(\s*)\S(?:.*\S)?(\s*)$/$1$t$2/s;
$ret="{{$oname";
$ret.='|'.join('|', @$params) if @$params;
$ret.="}}";
$log="{{$name}} with {{$t}}";
}
if($log eq ''){
push @remv, "{{$name}}";
} else {
push @repl, $log;
}
return $ret;
});
next if $fail;
# Need to edit?
if($outtxt ne $intxt){
if($unique){
my %x;
%x=(); @x{@repl}=(); @repl=keys %x;
%x=(); @x{@remv}=(); @remv=keys %x;
}
$repl[-1]='and '.$repl[-1] if @repl>1;
$remv[-1]='and '.$remv[-1] if @remv>1;
my $summary='';
if(@remv){
$summary.='Removing '.join((@remv>2)?', ':' ', @remv);
}
if(@repl){
$summary.=(@remv?'; and replacing ':'Replacing ').join((@repl>2)?', ':' ', @repl);
}
$summary.=" per $req";
$summary.=". $errors" if defined($errors);
$api->log("$summary in $title");
my $r=$api->edit($tok, $outtxt, $summary, 1, 1);
if($r->{'code'} ne 'success'){
$api->warn("Write failed on $title: ".$r->{'error'}."\n");
next;
}
} else {
$api->log("Nothing to do in $title");
}
$api->store->{$pageid}=$seq;
# If we've been at it long enough, let another task have a go.
return 0 if time()>=$endtime;
}
}
# No more pages to check, try again in 10 minutes or so in case of errors.
#$api->log("TemplateReplacer15 may be DONE!");
return 600;
}
1;