User:AnomieBOT/source/tasks/RedirectBypasser.pm

This is an old revision of this page, as edited by AnomieBOT (talk | contribs) at 02:29, 12 May 2012 (Updating published sources: RedirectBypasser: * New task. DatedCategoryCreater: * New task, coded against anticipated need. d::IWNS: * Allow multiple runs of spaces in namespace regex (e.g. as in User talk:AnomieBOT). AnomieBOT::API: * Include...). 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::RedirectBypasser;

=pod

=begin metadata

Bot:      AnomieBOT
Task:     RedirectBypasser
BRFA:     Wikipedia:Bots/Requests for approval/AnomieBOT 63
Status:   BRFA
Created:  2012-05-11
OnDemand: true

Bypass redirects in certain limited cases, e.g. to prevent confusion when a
username is being usurped, or to prepare for the repurposing of a shortcut
for an entirely different meaning.

=end metadata

=cut

use utf8;
use strict;

use POSIX;
use Data::Dumper;
use AnomieBOT::API;
use AnomieBOT::Task qw/bunchlist/;
use vars qw/@ISA/;
@ISA=qw/AnomieBOT::Task/;

# Page to notify of errors
my $notify='User talk:AnomieBOT';

# Page to notify of errors
my $summary='Bypassing redirects to prevent confusion after usurpation of [[User:N]], per [[User:AnomieBOT/req/Redirect bypass 1|request]]. Errors? [[User:AnomieBOT/shutoff/RedirectBypasser]]';

# List redirects to bypass
my @redirects=(
    'User:N',
    'User:N/Editcounter',
    'User:N/POTUSgallery',
    'User:N/admincoaching',
    'User:N/getqualified',
    'User:N/modern Jesus',
    'User:N/monobook.js',
    'User:N/mountainofskulls',
    'User talk:N',
    'User talk:N/Archive 1',
    'User talk:N/Archive 2',
    'User talk:N/Archive 3',
);

# List of pages to ignore
my @skip=(
    qr{^Wikipedia:Articles for deletion/Log/},
);

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

=pod

=for info
Approval requested<br />[[Wikipedia:Bots/Requests for approval/AnomieBOT 63]]

=cut

sub approved {
    return 0;
}

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

    $api->task('RedirectBypasser',0,0,qw/d::Talk d::Redirects d::Nowiki d::IWNS/);

    my %r=$api->resolve_redirects(@redirects);
    if(exists($r{''})){
        $api->warn("Failed to get redirects: ".$r{''}{'error'}."\n");
        return 60;
    }
    my %redirects=();
    my %re=();
    my $nsre=$api->namespace_re();
    my %nsmap=$api->namespace_map();
    while(my ($k,$v)=each %r){
        next if $k eq $v;
        $redirects{$k}=$v;
        my $re=$k;
        my $prefix='';
        $prefix.=$api->namespace_re($nsmap{$1})."[ _]*:[ _]*" if $re=~s/^($nsre)://;
        $prefix.="(?i:\Q$1\E)" if $re=~s/^(.)//;
        $re=quotemeta($re);
        $re=~s/\\ /[ _]+/g;
        $re='[ _]*'.$prefix.$re.'[ _]*';
        $re{$k}=qr/$re/;
    }
    unless(%redirects){
        $api->warn("No redirects to process!");
        return 3600;
    }

    my $skip=[];
    for my $re (@skip){
        $re=qr/^\Q$re\E$/ unless ref($re) eq 'Regexp';
        push @$skip, $re;
    }
    $skip=join('|',@$skip);
    $skip=qr/$skip/;

    my $iter=$api->iterator(
        generator    => 'backlinks',
        gbltitle     => [keys %redirects],
        gbllimit     => 'max',
    );
    while(my $p=$iter->next){
        return 0 if $api->halting;

        if(!$p->{'_ok_'}){
            $api->warn("Failed to retrieve backlinks for ".$iter->iterval.": ".$p->{'error'}."\n");
            return 60;
        }

        next if $p->{'title'}=~/$skip/;

        my $tok=$api->edittoken($p->{'title'}, EditRedir=>1);
        if($tok->{'code'} eq 'shutoff'){
            $api->warn("Task disabled: ".$tok->{'content'}."\n");
            return 300;
        }
        if($tok->{'code'} eq 'pageprotected'){
            $api->warn("Cannot edit $p->{title}: Page is protected\n");
            $api->whine("Cannot bypass redirects in [[:$p->{title}]]", "I cannot bypass redirects in [[:$p->{title}]], because the page is protected. Please bypass them manually. Thanks.", Pagename => $notify, NoSmallPrint => 1);
            next;
        }
        if($tok->{'code'} eq 'botexcluded'){
            $api->warn("Cannot edit $p->{title}: Bot exclusion applies\n");
            $api->whine("Cannot bypass redirects in [[:$p->{title}]]", "I cannot bypass redirects in [[:$p->{title}]], because I am excluded from editing that page using {{tl|bots}} or {{tl|nobots}}. Please bypass them manually. Thanks.", Pagename => $notify, NoSmallPrint => 1);
            next;
        }
        if($tok->{'code'} ne 'success'){
            $api->warn("Failed to get edit token for $p->{title}: ".$tok->{'error'}."\n");
            return 0;
        }

        my $intxt=$tok->{'revisions'}[0]{'*'};
        my ($outtxt,$nowiki)=$api->strip_nowiki($intxt);

        while(my ($k,$v)=each(%redirects)){
            my $re=$re{$k};
            $outtxt=~s/\[\[(?::[ _]*){0,2}$re\|/[[:$v|/g;
            $outtxt=~s/\[\[(?::[ _]*)?((?::[ _]*)?$re)\]\]/[[:$v|$1]]/g;
        }

        $outtxt=$api->replace_nowiki($outtxt, $nowiki);

        if($intxt ne $outtxt){
            $api->log("Bypassing redirects in $p->{title}");
            $res=$api->edit($tok, $outtxt, $summary, 1, 1);
            if($res->{'code'} ne 'success'){
                $api->warn("Write failed on $p->{title}: ".$res->{'error'}."\n");
                next;
            }
        } else {
            $api->warn("Cannot find redirects in $p->{title}\n");
            $api->whine("Cannot bypass redirects in [[:$p->{title}]]", "I cannot find the redirects to bypass in [[:$p->{title}]], although the API tells me they are there. Chances are it is either because of links generated by templates or unusual formatting breaking up the link text. Please bypass them manually. Thanks.", Pagename => $notify, NoSmallPrint => 1);
            next;
        }
    }

    $api->log("Task may be complete!");

    # No more pages to check for now
    return 600;
}

1;