User:AnomieBOT/source/tasks/AutoAssessor2.pm

This is an old revision of this page, as edited by AnomieBOT (talk | contribs) at 00:26, 26 November 2008 (Updating published sources: AutoAssessor2: * New task, AutoAssessor2. General: * A bit more sanitizing of the <code>$name</code> parameter.). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)
package tasks::AutoAssessor2;

=pod

=begin metadata

Task:   AutoAssessor2
BRFA:   Wikipedia:Bots/Requests for approval/AnomieBOT 15
Status: BRFA
Rate:   Max 6 edits/minute

Redirects and disambiguation pages will be automatically assessed with
class=redirect/disambig and importance=NA, stubs will be automatically assessed
with class=stub if not already assessed, and non-article pages will be
automatically assessed with the appropriate class 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
Approval requested<br />[[Wikipedia:Bots/Requests for approval/AnomieBOT 15]]

=cut

sub approved {
    return 0;
}

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

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

    # List of templates to assess in this task
    my @templates=('Physics');
    my $req='[[User talk:Anomie#Could you run AnomieBOT 8 again?]]';
    my $canonicalize=0;

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

    foreach my $template (@templates){
        my %q1=(
            generator    => 'embeddedin',
            geititle     => "Template:$template",
            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 { exists($_->{'subjectid'})?($_->{'subjectid'}):() } values %{$res->{'query'}{'pages'}};

            # 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=$self->fullquery($api, undef, %q2);
                foreach (values %{$res->{'query'}{'pages'}}){
                    my $pageid=$_->{'pageid'};
                    my $checked=$api->fetch($pageid);
                    next if defined($checked);

                    my ($imp,$impre,$class,$classre,$auto)=('',undef,'',undef,0);
                    if($_->{'ns'}==2){ # User
                        $class='NA';
                        $classre=qr/na/i;
                        $imp='NA';
                        $imp=qr/na/i;
                    } elsif($_->{'ns'}==4){ # Wikipedia
                        $class='project';
                        $classre=qr/project/i;
                        $imp='NA';
                        $imp=qr/na/i;
                    } elsif($_->{'ns'}==6){ # Image
                        $class='image';
                        $classre=qr/image/i;
                        $imp='NA';
                        $imp=qr/na/i;
                    } elsif($_->{'ns'}==8){ # MediaWiki
                        $class='NA';
                        $classre=qr/na/i;
                        $imp='NA';
                        $imp=qr/na/i;
                    } elsif($_->{'ns'}==10){ # Template
                        $class='template';
                        $classre=qr/template|templ|temp/i;
                        $imp='NA';
                        $imp=qr/na/i;
                    } elsif($_->{'ns'}==12){ # Help
                        $class='NA';
                        $classre=qr/na/i;
                        $imp='NA';
                        $imp=qr/na/i;
                    } elsif($_->{'ns'}==14){ # Category
                        $class='category';
                        $classre=qr/category|categ|cat/i;
                        $imp='NA';
                        $imp=qr/na/i;
                    } elsif($_->{'ns'}==100){ # Portal
                        $class='portal';
                        $classre=qr/portal/i;
                        $imp='NA';
                        $imp=qr/na/i;
                    } elsif($_->{'ns'}!='0'){
                        $class='NA';
                        $classre=qr/na/i;
                        $imp='NA';
                        $imp=qr/na/i;
                    } elsif(exists($_->{'redirect'})){
                        $class='redirect';
                        $classre=qr/redirect|red|redir/i;
                        $imp='NA';
                        $imp=qr/na/i;
                    } elsif(grep { $_->{'title'} eq 'Category:All disambiguation pages' } @{$_->{'categories'}}){
                        $class='disambig';
                        $classre=qr/disambig|dab/i;
                        $imp='NA';
                        $imp=qr/na/i;
                    } elsif(grep { $_->{'title'}=~/^Category:.* stubs?$/i } @{$_->{'categories'}}){
                        $class='stub';
                        $classre=qr/\S.*/is;
                        $auto=1;
                    } else {
                        # Save checked revision
                        $api->store($pageid, \1);
                        next;
                    }

                    my $title=$_->{'title'};
                    if($_->{'ns'}==0){
                        $title="Talk:$title";
                    } else {
                        $title=~s/^([^:]+):/$1 talk:/;
                    }

                    $self->warn("Assessing $title\n");

                    # Ok, check the page
                    my $tok=$api->edittoken($title, 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 $title: ".$tok->{'error'}."\n");
                        next;
                    }
                    next if exists($tok->{'missing'});

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

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

                        return undef unless exists($templates{"Template:$name"});

                        my $orig_param=join('|', @params);

                        if(defined($classre) && !grep(/^\s*class\s*=\s*$classre\s*$/s, @params)){
                            push @params, "class=$class" unless(grep(s/^(\s*class\s*=\s*).*?(\s*)$/$1$class$2/s, @params));
                            if($auto){
                                push @params, "auto=yes" unless grep(s/^(\s*auto\s*=\s*).*?(\s*)$/$1yes$2/s, @params);
                            } else {
                                @params = grep(!/^\s*auto\s*=/, @params);
                            }
                        }
                        if(defined($impre) && !grep(/^\s*importance\s*=\s*$impre\s*$/s, @params)){
                            push @params, "importance=NA" unless grep(s/^(\s*importance\s*=\s*).*?(\s*)$/${1}NA$2/s, @params);
                        }

                        my $new_param=join('|', @params);
                        push @found, "{{$name}}";
                        $any=1 if $orig_param ne $new_param;
                        if($canonicalize){
                            my $n=$templates{"Template:$name"};
                            $oname=~s/_/ /g;
                            $oname=~s/^(\s*)\S(?:.*\S)?(\s*)$/$1$n$2/is;
                        }
                        return "{{$oname|$new_param}}";
                    });

                    # Need to edit?
                    if($outtxt ne $intxt && $any){
                        $found[-1]='and '.$found[-1] if @found>1;
                        my $summary="Assessing ".join((@found>2)?', ':' ', @found)." as class=$class".(defined($impre)?" importance=$imp":"")." per $req";
                        $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");
                    }

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

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