User:AnomieBOT/source/tasks/TemplateReplacer14.pm

and parameters with imdb title, and tv.com in the External links section, respectively.

=end metadata

=cut

use utf8; use strict;

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

my $tv_extlink_templates_re=undef; my $no_edit_just_to_remove_parameters=0;

sub new { my $class=shift; my $self=$class->SUPER::new; bless $self, $class; return $self; }

=pod

=for info Approved 2009-03-03, completed 2009-03-26 Bots/Requests for approval/AnomieBOT 25

=cut

sub approved { return -1; }

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

$api->task('TemplateReplacer14', 0, 10, qw/d::Sections/);

return 60 if(!defined($api->load_interlanguage_map($api)));

if(!defined($tv_extlink_templates_re)){ my @links=; my $res=$api->query([],           list        => 'categorymembers',            cmtitle     => 'Category:Television external link templates',            cmnamespace => 10,            cmlimit     => 'max',        ); if($res->{'code'} ne 'success'){ $api->warn("Failed to retrieve tv external link template list: ".$res->{'error'}."\n"); return 60; }       #unshift @{$res->{'query'}{'categorymembers'}}, { title=>'Template:Official' }; foreach (@{$res->{'query'}{'categorymembers'}}){ my $t=$_->{'title'}; next if $t=~m{/(?:doc|sandbox)$}i; $t="\Q".substr($t,9); $t=~s/^(.)/(?i:$1)/; $t=~s/ /[ _]/g; push @links, $t; my $res2=$api->query([],               list          => 'backlinks',                bltitle       => $_->{'title'},                blfilterredir => 'redirects',                bllimit       => 'max',            ); if($res2->{'code'} ne 'success'){ $api->warn("Failed to retrieve redirects for ".$_->{'title'}.": ".$res2->{'error'}."\n"); return 60; }           foreach (@{$res2->{'query'}{'backlinks'}}){ $_="\Q".substr($_->{'title'},9); s/^Template:(.)/(?i:$1)/; s/ /[ _]/g; push @links, $_; }       }        $tv_extlink_templates_re=join('|', @links); $tv_extlink_templates_re=qr/)/o;   }

my $req="request";

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

$self->_output_log($api);

# Get a list of templates redirecting to our target my %templates=; $templates{"Template:Infobox Television"}=1; $res=$api->query([],       list          => 'backlinks',        bltitle       => "Template:Infobox Television",        blfilterredir => 'redirects',        bllimit       => 'max',    ); if($res->{'code'} ne 'success'){ $api->warn("Failed to retrieve redirects for Template:Infobox Television: ".$res->{'error'}."\n"); return 60; }   $templates{$_->{'title'}}=1 foreach (@{$res->{'query'}{'backlinks'}});

# Matching external links; "%X" is the text of the template parameter my @to_process=qw/imdb_id tv_com_id/; my %ext_links=(       'imdb_id' => [            'http://www.imdb.com/title/tt%X',            'http://www.imdb.com/title/tt%X/',            'http://imdb.com/title/tt%X',            'http://imdb.com/title/tt%X/',        ],        'tv_com_id' => [            'http://www.tv.com/show/%X/summary.html',            'http://tv.com/show/%X/summary.html',        ],    ); # External link generating templates; parameter 1 is the id, and optional # parameter 2 is the infobox's "show_name" parameter. my %ext_templates=(       'imdb_id' => 'imdb title',        'tv_com_id' => 'tv.com',    );

# Get the list of pages to check foreach my $cat ('Category:Television articles with an IMDb link in the infobox', 'Category:Television articles with a TV.com link in the infobox'){ my %q=(           list        => 'categorymembers',            cmtitle     => $cat,            cmnamespace => 0,            cmlimit     => 'max',        ); do { $res=$api->query(%q); if($res->{'code'} ne 'success'){ $api->warn("Failed to retrieve category member list for $cat: ".$res->{'error'}."\n"); return 60; }           if(exists($res->{'query-continue'})){ $q{'cmcontinue'}=$res->{'query-continue'}{'categorymembers'}{'cmcontinue'}; } else { delete $q{'cmcontinue'}; }

# Process found pages foreach (@{$res->{'query'}{'categorymembers'}}){ my $pageid=$_->{'pageid'}; next if exists($api->store->{$pageid});

# Cleanup the log my $log={}; $log=$api->store->{'log'} if exists($api->store->{'log'}); delete $log->{$_}{$pageid} foreach (keys %$log); $api->store->{'log'}=$log;

my $title=$_->{'title'}; $api->log("Processing $title");

# WTF? if(exists($_->{'missing'})){ $api->warn("$title is missing? WTF?\n"); next; }

# Ok, check the page my $tok=$api->edittoken($title); if($tok->{'code'} eq 'shutoff'){ $api->warn("Task disabled: ".$tok->{'content'}."\n"); return 300; }               if($tok->{'code'} ne 'success'){ $api->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]{'*'};

# Step 1: Find the parameters for the infobox. Also, strip the # parameters we are intending to process. my %infobox_params=; my $ct=0; my @process=; my $outtxt=$api->process_templates($intxt, sub {                   my $name=shift;                    my @params=@{shift};                    shift; # $wikitext                    shift; # $data                    my $oname=shift;

return undef unless exists($templates{"Template:$name"}); if($ct++>0){ # More than one infobox? $self->_log($api, 'Multiple infoboxen', $pageid, $title, "$ct instances of the infobox detected."); $api->store->{$pageid}=1; return undef; }                   my @out=; foreach ($api->process_paramlist(@params)){ $_->{'value'}=~s/^\s+|\s+$//g; $infobox_params{$_->{'name'}}=$_->{'value'} unless $_->{'value'} eq ''; if(exists($ext_links{$_->{'name'}})){ push @process, $_->{'name'} unless $_->{'value'} eq ''; } else { push @out, $_->{'text'}; }                   }                    return ""; });               next if $ct>1;                if($ct<1){                    $self->_log($api, 'No infobox', $pageid, $title, "No instance of the infobox was found in the page.");                    $api->store->{$pageid}=2;                    next;                }                unless(@process){                    # Nothing to do here.                    $api->store->{$pageid}=1000000;                    next;                }

# Step 2: Extract the external links section my $nowiki; ($outtxt,$nowiki)=$api->strip_nowiki($outtxt); my $comments=[]; while(my ($k,$v)=each(%$nowiki)){ push @$comments, $k if $v=~/^replace_nowiki($split[$i+0], $nowiki); $h=~s/^(\n?==)(=?)\s*External\s*(\2==)$/$1$2 External links $3/i; $h=~s/^(\n?==)(=?)(.*)External link\(s\)(.*\2==)$/$1$2$3External links$4/i; $h=~s/^(\n?==)(=?)(.*)External link((?!s).*\2==)$/$1$2$3External links$4/i; $h=~s/^(\n?==)(=?)(.*)External references?(.*\2==)$/$1$2$3External links$4/i; my $s=$h.$api->replace_nowiki($split[$i+2], $nowiki); push @sections, \$s; $extlink_section=\$s if $h=~/External links/i; }               if(!defined($extlink_section)){ # Crap, we have to create an external links section. $self->_log($api, 'Added "External links"', $pageid, $title, "No \"External links\" section was found in the page. Check if one was added in the right place."); my $x=pop @sections; my ($pre,$post)=$api->extract_end_content($$x); return 60 if(!defined($pre)); $pre=~s/\s+$/\n/; push @sections, \$pre; my $dummy="\n== External links ==\n\n"; $extlink_section=\$dummy; push @sections, $extlink_section; push @sections, \$post; } elsif($extlink_section==$sections[-1]){ # Last section, strip off the post-content junk my $x=pop @sections; my ($pre,$post)=$api->extract_end_content($$x); return 60 if(!defined($pre)); $extlink_section=\$pre; push @sections, $extlink_section; push @sections, \$post; }

# Step 3: Process our parameters my $res=$api->query([],                   action=>'parse',                    text=>$$extlink_section,                    prop=>'externallinks',                ); if($res->{'code'} ne 'success'){ $api->warn("Failed to parse external links section for $title: ".$res->{'error'}."\n"); return 60; }               my @el=; @el=@{$res->{'parse'}{'externallinks'}} if exists($res->{'parse'}{'externallinks'}); my $add=''; my $has_website=0; PARAM: foreach my $param (@to_process){ next unless grep($_ eq $param, @process); my $id=$infobox_params{$param}; foreach (@{$ext_links{$param}}){ my $link=$_; $link=~s/%X/$id/g; next PARAM if grep($_ eq $link, @el); }                   my $tmpl=$ext_templates{$param}; $add.="\n* "; $has_website=1 if $param eq 'website'; }

# Step 4: Reassemble the page, if anything changed in step 3 if($add ne ''){ if($has_website && $$extlink_section=~s/\n\*/$add\n*/){ # Move "website" to the top of the external links } elsif($$extlink_section=~s/(\n\*\s*$tv_extlink_templates_re.*?)\n/$1$add\n/){ # Put it after any other existing tv external link # templates } elsif($$extlink_section=~s/(\s*\n===)/$add$1/){ # There is a subsection in there (e.g. "Reviews"), put # the links before it. } else { # Just tack it on the end. $$extlink_section=~s/(\s*)$/$add$1/; }                   $outtxt=join('', map { $$_ } @sections); } elsif($no_edit_just_to_remove_parameters){ $api->store->{$pageid}=1000001; next; } else { $outtxt=$api->replace_nowiki($outtxt, $nowiki); }

# Step 5: Perform the edit. $process[-1]='and '.$process[-1] if @process>1; my $summary='Moving deprecated '.join((@process>2)?', ':' ', @process).' from to External links per '.$req; $api->log("$summary in $title"); my $r=$api->edit($tok, $outtxt, $summary, 0, 1); if($r->{'code'} ne 'success'){ $api->warn("Write failed on $title: ".$r->{'error'}."\n"); next; }

# Mark this page as done $api->store->{$pageid}=2000000;

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

# No more pages to check, try again in 10 minutes or so in case of errors. $self->_output_log($api); return 600; }

sub _log { my $self=shift; my $api=shift; my $section=shift; my $pageid=shift; my $title=shift; my $message=shift;

my $log={}; $log=$api->store->{'log'} if exists($api->store->{'log'}); $log->{$section}={} unless exists($log->{$section}); $log->{$section}{$pageid}=[$title, $message]; $api->store->{'log'}=$log; $api->log("LOG: $title: $message"); }

sub _output_log { my $self=shift; my $api=shift;

$api->log("Updating log"); my $tok=$api->edittoken("User:AnomieBOT/TemplateReplacer14 log"); if($tok->{'code'} eq 'shutoff'){ $api->warn("Task disabled: ".$tok->{'content'}."\n"); return 300; }   if($tok->{'code'} ne 'success'){ $api->warn("Failed to get edit token for log: ".$tok->{'error'}."\n"); return; }   my $header="This is a log of issues encountered during the processing of the task TemplateReplacer14. Do not edit this page, the bot will overwrite it.\n"; my $intxt=exists($tok->{'missing'})?$header:$tok->{'revisions'}[0]{'*'}; my $outtxt=$header; my $log={}; $log=$api->store->{'log'} if exists($api->store->{'log'}); foreach my $section (sort keys %$log){ my @out=; foreach my $pageid (keys %{$log->{$section}}){ next unless exists($api->store->{$pageid}); my ($title,$message)=@{$log->{$section}{$pageid}}; push @out, "* $title: $message\n"; }       next unless @out; $outtxt.="\n== $section ==\n".join('', @out) if @out; }   if($outtxt ne $intxt){ my $r=$api->edit($tok, $outtxt, 'Updating log', 0, 0); if($r->{'code'} ne 'success'){ $api->warn("Could not write log: ".$r->{'error'}."\n"); return; }   } }

1;