User:AnomieBOT/source/tasks/AutoAssessor.pm

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

=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:    AutoAssessor
BRFA:    Wikipedia:Bots/Requests for approval/AnomieBOT 8
Status:  Completed 2008-10-30
Created: 2008-10-28

Assess existing {{tl|Physics}} and {{tl|WPAstronomy}} on talk pages of
redirect/disambig pages with class=redirect/disambig and importance=NA.

=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 2008-10-30, Completed 2008-10-30<br />[[Wikipedia:Bots/Requests for approval/AnomieBOT 8]]

=cut

sub approved {
    return -1;
}

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

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

    # List of templates to replace in this task
    my @templates=('Physics', 'WPAstronomy');

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

    foreach my $template (@templates){
        my %q1=(
            generator    => 'embeddedin',
            geititle     => "Template:$template",
            geinamespace => "1",
            geilimit     => 'max',
            prop         => 'info',
            inprop       => 'subjectid',
        );
        my %q2=(
            pageids  => '',
            prop     => 'info|categories',
            cllimit  => 'max',
        );

        # Get the list of pages to check
        do {
            $res=$api->query(%q1);
            if($res->{'code'} ne 'success'){
                $self->warn("Failed to retrieve transclusion list for $template: ".$res->{'error'}."\n");
                return 60;
            }
            if(exists($res->{'query-continue'})){
                $q1{'geicontinue'}=$res->{'query-continue'}{'embeddedin'}{'geicontinue'};
            } else {
                delete $q1{'geicontinue'};
            }

            # Collect page IDs of articles for found talk pages
            my %pageids=map { $_->{'subjectid'} => $_->{'lastrevid'} } values %{$res->{'query'}{'pages'}};
            my @pageids=keys %pageids;

            # Look up info for found pages, in blocks of 500 because that's the
            # max pageids per query allowed.
            while(@pageids){
                $q2{'pageids'}=join('|', splice(@pageids, 0, 500));
                $res=$api->query(%q2);
                foreach (values %{$res->{'query'}{'pages'}}){
                    my $pageid=$_->{'pageid'};
                    my $revid=[$pageids{$pageid}, $_->{'lastrevid'}];
                    my $checked=$api->fetch($pageid);
                    next if(defined($checked) && $checked->[0] eq $revid->[0] && $checked->[1] eq $revid->[1]);

                    my ($class,$classre);
                    if(exists($_->{'redirect'})){
                        $class='redirect';
                        $classre=qr/[rR]edirect/;
                    } elsif(grep { $_->{'title'} eq 'Category:All disambiguation pages' } @{$_->{'categories'}}){
                        $class='disambig';
                        $classre=qr/[dD]isambig(?:uation)?|DAB|[dD]ab/;
                    } else {
                        # Save checked revision
                        $api->store($pageid, $revid);
                        next;
                    }
                    my $title=$_->{'title'};

                    $self->warn("Checking for templates in Talk:$title (for $class)\n");

                    # Ok, check the page
                    my $tok=$api->edittoken("Talk:$title", EditRedir => 1);
                    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 Talk:$title: ".$tok->{'error'}."\n");
                        next;
                    }
                    next if exists($tok->{'missing'});
                    if($tok->{'lastrevid'} ne $revid->[0]){
                        $self->warn("Talk:$title edited since loaded, skipping\n");
                        next;
                    }

                    # Get page text
                    my $intxt=$tok->{'revisions'}[0]{'*'};

                    # Now, we actually perform the replacement
                    my @found=();
                    my $minor=1;
                    my $outtxt=$self->process_templates($intxt, sub {
                        my $name=shift;
                        my @params=@{shift()};
                        shift; # $wikitext
                        shift; # $data
                        my $oname=shift;

                        $name=~s/_/ /g;
                        return undef unless exists($templates{'Template:'.ucfirst($name)});
                        if(grep(/^\s*class\s*=\s*$classre\s*$/, @params) &&
                           grep(/^\s*importance\s*=\s*[Nn][Aa]\s*$/, @params)){
                           # Already tagged
                           next;
                        }

                        # Tag
                        push @params, "class=$class" unless grep(s/^(\s*class\s*=\s*).*?(\s*)$/$1$class$2/s, @params);
                        push @params, "importance=NA" unless grep(s/^(\s*importance\s*=\s*).*?(\s*)$/${1}NA$2/s, @params);
                        @params = grep(!/^\s*auto\s*=/, @params);

                        # Ok, return the new template code now.
                        push @found, "{{$name}}";
                        return "{{$oname|".join("|", @params)."}}";
                    });
                    $found[-1]='and '.$found[-1] if @found>1;
                    my $summary="Assessing ".join((@found>2)?', ':' ', @found)." as class=$class importance=NA per [[WP:BOTREQ#Tagging and assessing .7B.7BPhysics.7D.7D and .7B.7BWPAstronomy.7D.7D redirect and disambiguation pages|request]]";

                    # Need to edit?
                    if($outtxt ne $intxt){
                        $self->warn("$summary in $title\n");
                        my $r=$api->edit($tok, $outtxt, $summary, $minor, $minor);
                        if($r->{'code'} ne 'success'){
                            $self->warn("Write failed on $title: ".$r->{'error'}."\n");
                            next;
                        }
                        $revid->[0]=$r->{'edit'}{'newrevid'};
                    } else {
                        $self->warn("Nothing to do in $title\n");
                    }

                    # Save checked revision
                    $api->store($pageid, $revid);

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

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

1;