User:AnomieBOT/source/tasks/TemplateReplacer15.pm

{{ombox|type=notice|text= 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/;

  1. Sequence number

my $seq=10;

my $req="request";

my $errors="Errors or discussion? Post a note here to stop the bot.";

my $force=1;

my $unique=1;

  1. List of templates to remove/replace in this task. Values may be the new
  2. template name (simple replacement), the empty string (removal), or a function
  3. ref (something more complicated).

my %repl=(

'Template:Citation needed' => \&repl,

);

my @templates=keys %repl;

  1. 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}}");

};

  1. 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,

);

  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
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;