User:AnomieBOT/source/tasks/TemplateReplacer12.pm

From Wikipedia, the free encyclopedia
package tasks::TemplateReplacer12;

=pod

=for warning
Due to breaking changes in AnomieBOT::API, this task will probably not run
anymore. If you really must run it, try getting a version from before
2009-03-23.

=begin metadata

Bot:     AnomieBOT
Task:    TemplateReplacer12
BRFA:    Wikipedia:Bots/Requests for approval/AnomieBOT 23
Status:  Completed 2009-01-19
Created: 2009-01-15

Replace {{tlx|Film needs cast section}}, {{tlx|Filmimage}}, and {{tlx|Film
needs synopsis}} (and redirects) with {{tlx|Film}} with appropriate needs-X
parameters. Also, perform some cleanup to {{tlx|Film}} on pages edited for this
reason.

=end metadata

=cut

use utf8;
use strict;

use AnomieBOT::Task;
use vars qw/@ISA/;
@ISA=qw/AnomieBOT::Task/;

sub new {
    my $class=shift;
    my $self=$class->SUPER::new();
    bless $self, $class;
    return $self;
}

=pod

=for info
Approved 2009-01-16, Completed 2009-01-19<br />[[Wikipedia:Bots/Requests for approval/AnomieBOT 23]]

=cut

sub approved {
    return -1;
}

sub run {
    my ($self, $api)=@_;
    my $res;

    $api->task('TemplateReplacer12');
    $api->read_throttle(0);
    $api->edit_throttle(10);

    # List of templates to replace in this task
    my %tf=(
        'Film needs cast section' => 'needs-cast',
        'Filmimage' => 'needs-image',
        'Film needs synopsis' => 'needs-synopsis',
    );
    my @templates=keys %tf;
    my $req="[[WP:BOTREQ#More .7B.7BFilm.7D.7D cleanup|request]]";

    # 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=();
    foreach my $template (@templates){
        $templates{"Template:$template"}=$tf{$template};
        $res=$api->query([],
            list          => 'backlinks',
            bltitle       => "Template:$template",
            blfilterredir => 'redirects',
            bllimit       => 'max',
        );
        $templates{$_->{'title'}}=$tf{$template} foreach (@{$res->{'query'}{'backlinks'}});
    }

    # Before starting, get the list of alternate names for our target
    my %WPF=('Template:Film'=>1);
    $res=$api->query([],
        list          => 'backlinks',
        bltitle       => 'Template:Film',
        blfilterredir => 'redirects',
        bllimit       => 'max',
    );
    $WPF{$_->{'title'}}=1 foreach (@{$res->{'query'}{'backlinks'}});
    delete $WPF{$_} foreach (values %templates);

    # Also, get redirects to WikiProjectBanners and WikiProjectBannerShell, for
    # renumbering if necessary
    my %WPB=();
    my %B=('Template:WikiProjectBanners'=>1,'Template:WikiProjectBannerShell'=>2);
    while(my ($t,$c)=each %B){
        $WPB{$t}=$c;
        $res=$api->query([],
            list          => 'backlinks',
            bltitle       => $t,
            blfilterredir => 'redirects',
            bllimit       => 'max',
        );
        if($res->{'code'} ne 'success'){
            $self->warn("Failed to retrieve redirect list for $t: ".$res->{'error'}."\n");
            return 60;
        }
        $WPB{$_->{'title'}}=$c foreach (@{$res->{'query'}{'backlinks'}});
    }

    foreach my $template (@templates){
        # Get the list of pages to check
        my %q=(
            list    => 'embeddedin',
            eititle => "Template:$template",
            eilimit => 'max',
        );
        do {
            $res=$api->query(%q);
            if($res->{'code'} ne 'success'){
                $self->warn("Failed to retrieve transclusion list for $template: ".$res->{'error'}."\n");
                return 60;
            }
            if(exists($res->{'query-continue'})){
                $q{'eicontinue'}=$res->{'query-continue'}{'embeddedin'}{'eicontinue'};
            } else {
                delete $q{'eicontinue'};
            }

            # Process found pages
            foreach (@{$res->{'query'}{'embeddedin'}}){
                my $title=$_->{'title'};
                $self->warn("Checking for $template in $title\n");

                # WTF?
                if(exists($_->{'missing'})){
                    $self->warn("$title is missing? WTF?\n");
                    next;
                }

                # Ok, check the page
                my $tok=$api->edittoken($title);
                if($tok->{'code'} eq 'shutoff'){
                    $self->warn("Task disabled: ".$tok->{'content'}."\n");
                    return 300;
                }
                if($tok->{'code'} ne 'success'){
                    $self->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]{'*'};

                # First step is to determine if the replacement is already on
                # the page.
                my $has_WPF=0;
                my %tf=();
                $self->process_templates($intxt, sub {
                    $has_WPF=1 if exists($WPF{'Template:'.$_[0]});
                    return undef unless exists($templates{'Template:'.$_[0]});
                    $tf{$templates{'Template:'.$_[0]}}='{{'.$_[0].'}}';
                    return undef;
                });

                # Now, we actually perform the replacement
                my @a=values %tf;
                $a[-1]='and '.$a[-1] if @a>1;
                my $summary="Replacing ".join((@a>2)?', ':' ', @a)." with {{Film|".join("=yes|",keys %tf)."=yes}} (and removing unused parameters) per $req";
                my $outtxt=$self->process_templates($intxt, sub {
                    my $name=shift;
                    my @params=@{shift()};
                    shift; # $wikitext
                    shift; # $data
                    my $oname=shift;

                    if(exists($templates{"Template:$name"})){
                        return '' if $has_WPF;
                        $has_WPF=1;
                        $oname=~s/\Q$name\E/Film/i;
                        $name='Film';
                    }
                    return undef unless exists($WPF{"Template:$name"});

                    # We have the replacement template now, either by finding
                    # the existing one or by replacing the target template if
                    # none was already present. Now, set the various need-X
                    # parameters.
                    foreach (keys %tf){
                        @params=grep(!/^\s*\Q$_\E\s*=\s*$/, @params);
                        push @params, "$_=yes" if(!grep(/^\s*\Q$_\E\s*=/, @params));
                    }

                    # Since we're here anyway, clean up the Film parameters.
                    @params=grep(!/^\s*(?:importance|attention|auto|portal[12345]-name)\s*=/, @params);
                    my $n='Film';
                    $oname=~s/^(\s*)\S(?:.*\S)?(\s*)$/$1$n$2/s;

                    # Ok, return the new template code now.
                    return "{{$oname|".join("|", @params)."}}";
                });

                # Need to edit?
                if($outtxt ne $intxt){
                    # Post-process to fix
                    # WikiProjectBanners/WikiProjectBannerShell numbering.
                    $outtxt=$self->process_templates($outtxt, sub {
                        my $name=shift;
                        my @params=@{shift()};
                        shift; # $wikitext
                        shift; # $data
                        my $oname=shift;

                        return undef unless exists($WPB{"Template:$name"});
                        my @p_name=();
                        my @p_num=();
                        foreach ($self->process_paramlist(@params)){
                            if($_->{'name'}=~/^\d+$/){
                                push @p_num, $_->{'value'} unless $_->{'value'}=~/^\s*$/;
                            } else {
                                push @p_name, $_->{'text'};
                            }
                        }
                        for(my $i=0; $i<@p_num; $i++){
                            push @p_name, ($i+1).'='.$p_num[$i];
                        }
                        return "{{$oname|".join("|", @p_name)."}}";
                    });

                    $self->warn("$summary in $title\n");
                    my $r=$api->edit($tok, $outtxt, $summary, 1, 1);
                    if($r->{'code'} ne 'success'){
                        $self->warn("Write failed on $title: ".$r->{'error'}."\n");
                        next;
                    }
                } else {
                    $self->warn("Nothing to do in $title\n");
                }

                # If we've been at it long enough, let another task have a go.
                return 0 if time()>=$endtime;
            }
        } while(exists($q{'eicontinue'}));
    }

    # No more pages to check, try again in 10 minutes or so in case of errors.
    return 600;
}

1;