User:AnomieBOT/source/tasks/RedirectBypasser.pm

This is an old revision of this page, as edited by AnomieBOT (talk | contribs) at 17:04, 6 June 2012 (Updating published sources: RedirectBypasser: * Prepare for trial run.). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
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, currently:
* To prevent confusion when a username is being usurped.

=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:Nard the Bard';

# 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/},
    'Wikipedia:Changing username/Usurpations',
    'Wikipedia:Changing username/Usurpations/Completed/33',
    'User talk:Nard the Bard',
    'User talk:N',
);

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);
            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);
            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);
            next;
        }
    }

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

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

1;