package tasks::WatchlistUpdater;
use strict;
use AnomieBOT::Task;
use vars qw/@ISA/;
@ISA=qw/AnomieBOT::Task/;
use POSIX qw/strftime/;
use Data::Dumper;
my %pages=(
'User:Anomie/uw-templates' => {
frequency => 12*60*60,
list => 'allpages',
apprefix => 'Uw-',
apnamespace => '10',
aplimit => 'max'
}
);
my $maxlen=100*1024*1024;
sub approved {
# Per [[WP:BOT#Approval]], any bot or automated editing process that only
# affects only the operators' user and talk pages (or subpages thereof),
# and which are not otherwise disruptive, may be run without prior
# approval.
return 1;
}
sub run {
my ($self, $api)=@_;
my ($k,$v,$k2,$v2,$k3,$v3,@x);
$api->task('WatchlistUpdater 1.0');
$api->read_throttle(6);
$api->edit_throttle(10);
return 300 if $self->check_shutoff($api, 'WatchlistUpdater');
if(!exists($self->{'lastrun'})){
my %lastrun=();
values(%pages);
while(($k,$v)=each(%pages)){
my $res=$api->query(
titles => $k,
prop => 'revisions',
rvuser => $api->user,
rvprop => 'timestamp',
rvlimit => 1
);
if($res->{'code'} ne 'success'){
warn "Failed to retrieve last edit date for $k, cannot run task";
return 60;
}
$res=[values(%{$res->{'query'}{'pages'}})];
if(exists($res->[0]{'revisions'}[0]{'timestamp'})){
$lastrun{$k}=$self->ISO2timestamp($res->[0]{'revisions'}[0]{'timestamp'});
} else {
$lastrun{$k}=0;
}
}
$self->{'lastrun'}=\%lastrun;
}
while(($k,$v)=each(%pages)){
next unless time()>=$self->{'lastrun'}{$k}+$v->{'frequency'};
my $starttime=strftime("%d %b %Y %T", gmtime());
my $tok=$api->edittoken($k);
if($tok->{'code'} ne 'success'){
$self->warn("Failed to retrieve edit token for $k: ".$tok->{'error'});
next;
}
if(exists($tok->{'missing'})){
$self->warn("Page $k does not exist");
next;
}
my $intxt=$tok->{'revisions'}[0]{'*'};
my $table="{| class=\"wikitable\"\n";
my %q=%$v;
delete($q{'frequency'});
my $res;
do {
$res=$api->query(%q);
if($res->{'code'} ne 'success'){
$self->warn("Failed to retrieve data for $k: ".$res->{'error'});
next;
}
if(exists($res->{'query-continue'})){
while(($k2,$v2)=each(%{$res->{'query-continue'}})){
while(($k3,$v3)=each(%$v2)){
$q{$k3}=$v3;
}
}
}
while(length($table)<$maxlen && (($k2,$v2)=each(%{$res->{'query'}}))){
if(ref($v2) eq 'HASH'){
@x=values(%$v2);
} elsif(ref($v2) eq 'ARRAY'){
@x=@$v2;
} else {
next;
}
for(my $i=0; $i<@x; $i++){
if($x[$i]{'ns'}==0){
$v2="\x5b\x5b".$x[$i]{'title'}."\x5d\x5d";
$v3="\x5b\x5bTalk:".$x[$i]{'title'}."\x5d\x5d";
} elsif($x[$i]{'ns'}==1){
$v3="\x5b\x5b".$x[$i]{'title'}."\x5d\x5d";
($v2=$v3)=~s/Talk://i;
} elsif(($x[$i]{'ns'}&1)==0){
$v2="\x5b\x5b".$x[$i]{'title'}."\x5d\x5d";
($v3=$v2)=~s/^([^:]+):/$1 talk:/;
} else {
$v3="\x5b\x5b".$x[$i]{'title'}."\x5d\x5d";
($v2=$v3)=~s/ talk:/:/i;
}
$table.="|-\n|$v2 || $v3\n";
}
}
} while(length($table)<=$maxlen && exists($res->{'query-continue'}));
$table.="|}";
$table='<strong class="error">List of pages is too long</strong>' if length($table)>$maxlen;
$table=~s/\x5b\x5b(Category|Image):/\x5b\x5b:$1:/ig;
my $endtime=strftime("%d %b %Y %T", gmtime());
my ($i,$j);
$i=index($intxt,'<!-- SNIP HERE -->');
$j=index($intxt,"{| class=\"wikitable\"\n",($i<0)?0:$i);
my $t=($j<0)?'':substr($intxt,$j);
$t=~s/\s+$//;
if($t eq $table){
$self->warn("No update needed for $k\n");
$self->{'lastrun'}{$k}=time();
next;
}
my $outtxt=$intxt;
$outtxt=substr($outtxt,0,$i) if $i>=0;
$outtxt.="<!-- SNIP HERE -->\n<small>Last update happened between $starttime GMT and $endtime GMT</small>\n$table";
$res=$api->edit($tok, $outtxt, 'Updating list of watched pages', 0, 1);
if($res->{'code'} eq 'success'){
$self->warn("Updated $k\n");
$self->{'lastrun'}{$k}=time();
} else {
$self->warn("Write for $k failed: ".$res->{'error'});
}
}
my $t=864000;
while(($k,$v)=each(%pages)){
my $tt=$self->{'lastrun'}{$k}+$v->{'frequency'}-time();
$t=$tt if $tt<$t;
}
$t=300 if $t<300;
return $t;
}