User:AnomieBOT/source/tasks/TemplateReplacer.pm

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

=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:    TemplateReplacer
BRFA:    Wikipedia:Bots/Requests for approval/AnomieBOT 2
Status:  Completed 2008-09-04
Created: 2008-08-31

Replace {{tl|WP MMOG}} (and old redirects) with {{tl|WikiProject Video games}}.
Also canonicalizes redirects to {{tl|WikiProject Video games}} on the pages it
edits for this reason, since it's editing them anyway.

=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
BRFA approved 2008-09-04, task completed 2008-09-04<br />[[Wikipedia:Bots/Requests for approval/AnomieBOT 2]]

=cut

sub approved {
    return -1;
}

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

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

    # Spend a max of 5 minutes on this task before restarting
    my $endtime=time()+300;

    # Before starting, get the list of alternate names for {{WikiProject Video
    # games}}
    my %WPVG=('Template:WikiProject Video games'=>1);
    $res=$api->query([],
        list          => 'backlinks',
        bltitle       => 'Template:WikiProject Video games',
        blfilterredir => 'redirects',
        bllimit       => 'max',
    );
    $WPVG{$_->{'title'}}=1 foreach (@{$res->{'query'}{'backlinks'}});
    delete $WPVG{'Template:WP MMOG/RS'};
    delete $WPVG{'Template:WP MMOG'};
    delete $WPVG{'Template:WP MMO'};

    # Also, get redirects to WikiProjectBanners and WikiProjectBannerShell, for
    # renumbering after the wikiproject banner is removed.
    my %WPB=('Template:WikiProjectBanners'=>1,'Template:WikiProjectBannerShell'=>1);
    $res=$api->query([],
        list          => 'backlinks',
        bltitle       => 'Template:WikiProjectBanners',
        blfilterredir => 'redirects',
        bllimit       => 'max',
    );
    $WPB{$_->{'title'}}=1 foreach (@{$res->{'query'}{'backlinks'}});
    $res=$api->query([],
        list          => 'backlinks',
        bltitle       => 'Template:WikiProjectBannerShell',
        blfilterredir => 'redirects',
        bllimit       => 'max',
    );
    $WPB{$_->{'title'}}=1 foreach (@{$res->{'query'}{'backlinks'}});

    foreach my $template ('WP MMO','WP MMOG','WP MMOG/RS'){
        # First, 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 {{WikiProject Video games}} is
                # already on the page.
                my $has_WPVG=0;
                $self->process_templates($intxt, sub {
                    $has_WPVG=1 if exists($WPVG{'Template:'.ucfirst($_[0])});
                    return undef;
                });

                # Now, we actually perform the replacement
                my $append='';
                my $summary="Replacing {{$template}} with {{WikiProject Video games}} per [[WP:BOTREQ#Template Deletion bot|request]]";
                my $minor=1;
                my $outtxt=$self->process_templates($intxt, sub {
                    my $name=shift;
                    my @params=@{shift()};

                    $name=~s/_/ /g;
                    if(ucfirst($name) eq $template){
                        return '' if $has_WPVG;
                        $name='WikiProject Video games';
                        @params=grep(/^\s*(?:class|importance|small|nested)\s*=/, @params);
                        #push @params, 'tf=MU*';
                    }
                    return undef unless exists($WPVG{'Template:'.ucfirst($name)});

                    # We have the WPVG template now, either by finding the
                    # existing one or by replacing the MMO template if no WPVG
                    # was already present. Now, find if there is already a 'tf'
                    # for this task force.
                    # Or not. Apparently that was a poorly worded request.
                    #my @tf=grep(/^\s*tf[23]?\s*=\s*MU\*\s*$/, @params);
                    #if(!@tf){
                    #    if(!grep(/^\s*tf\s*=/, @params)){
                    #        push @params, 'tf=MU*';
                    #    } elsif(!grep(/^\s*tf2\s*=/, @params)){
                    #        push @params, 'tf2=MU*';
                    #    } elsif(!grep(/^\s*tf3\s*=/, @params)){
                    #        push @params, 'tf3=MU*';
                    #    } else {
                    #        $append="\n==Template:$template removal issue==\nPer a [[WP:BOTREQ#Template Deletion bot|bot request]], I am going through all pages transcluding {{tl|$template}} to remove it and add a <code>tf=MU*</code> parameter to the {{tl|WikiProject Video games}} template instead. Unfortunately, this page already uses all three of <code>tf</code>, <code>tf2</code>, and <code>tf3</code> in its {{tl|WikiProject Video games}}, so human intervention is required. ~~~~";
                    #        $summary="Human intervention needed to replace {{$template}} with {{WikiProject Video games|tf=MU*}} per [[WP:BOTREQ#Template Deletion bot|request]]";
                    #        $minor=0;
                    #    }
                    #}

                    # Ok, return the new template code now.
                    return "{{WikiProject Video games|".join("|", @params)."}}";
                });
                $outtxt.=$append;

                # 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()};

                        $name=~s/_/ /g;
                        return undef unless exists($WPB{'Template:'.ucfirst($name)});
                        my $idx=0;
                        my $out='{{'.$name;
                        foreach (@params){
                            if(/^\s*\d+\s*=\s*$/s){
                                # skip it
                            } elsif(/^\s*\d+\s*=(.*)$/s){
                                ++$idx;
                                $out.="|$idx=$1";
                            } else {
                                $out.='|'.$_;
                            }
                        }
                        $out.='}}';
                        return ($idx<=1)?undef:$out;
                    });

                    $self->warn("$summary in $title\n");
                    my $r=$api->edit($tok, $outtxt, $summary, $minor, 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;