User:AnomieBOT/source/tasks/MedComClerk.pm
Appearance
Approved 2011-02-03. Wikipedia:Bots/Requests for approval/MediationBot |
Bot is currently inactive, as MedCom is closed. |
package tasks::MedComClerk;
=pod
=begin metadata
Bot: MediationBot
Task: MedComClerk
BRFA: Wikipedia:Bots/Requests for approval/MediationBot
Status: Inactive 2018-11-12
Created: 2011-01-12
Perform basic clerking tasks at [[Wikipedia:Requests for mediation]].
=end metadata
=cut
use utf8;
use strict;
use AnomieBOT::Task qw/:time/;
use Data::Dumper;
use vars qw/@ISA/;
@ISA=qw/AnomieBOT::Task/;
my $version=0;
sub new {
my $class=shift;
my $self=$class->SUPER::new();
bless $self, $class;
return $self;
}
=pod
=for info
Approved 2011-02-03.<br />[[Wikipedia:Bots/Requests for approval/MediationBot]]
=for info
Bot is currently inactive, as MedCom is closed.
=cut
sub approved {
return -210;
}
sub run {
my ($self, $api)=@_;
my $res;
$api->task('MedComClerk', 0, 10, qw/d::Sections d::Timestamp d::Talk/);
my $screwup=' Errors? [[User:'.$api->user.'/shutoff/MedComClerk]]';
my $b0rken=0;
my $botname=$api->user;
my $starttime=time();
if($api->store->{'version'}//0 < $version){
$api->store->{'Members revid'}=0;
$api->store->{'version'} = $version;
}
# Get the last rev ID for the members list, to skip downloading the
# entire page if not necessary.
$res=$api->query(titles=>'Wikipedia:Mediation Committee/Members', prop=>'revisions', rvprop=>'ids');
if($res->{'code'} ne 'success'){
$api->warn("Failed to get revids: ".$res->{'error'}."\n");
return 60;
}
my ($Members_revid)=(undef);
foreach (values %{$res->{'query'}{'pages'}}){
$Members_revid=$_->{'revisions'}[0]{'revid'} if $_->{'title'} eq 'Wikipedia:Mediation Committee/Members';
}
if(!defined($Members_revid)){
$api->warn("Response was missing required revids: ".$res->{'error'}."\n");
return 60;
}
# Load the list of committee members, if necessary
my @Members;
if($Members_revid==($api->store->{'Members revid'} // 0)){
@Members=@{$api->store->{'Members'}};
} else {
$res=$api->query(
titles => 'Wikipedia:Mediation Committee/Members',
prop => 'revisions',
rvprop => 'content',
rvslots => 'main',
);
if($res->{'code'} ne 'success'){
$api->warn("Failed to get Wikipedia:Mediation Committee/Members: ".$res->{'error'}."\n");
return 60;
}
@Members=();
my $txt=(values %{$res->{'query'}{'pages'}})[0]{'revisions'}[0]{'slots'}{'main'}{'*'};
$api->process_templates($txt, sub {
my $name=shift;
my $params=shift;
return undef unless $name eq '/Table' || $name eq 'Wikipedia:Mediation Committee/Members/Table';
foreach ($api->process_paramlist(@$params)){
next unless $_->{'name'} eq 'user';
$_->{'value'}=~s/^\s*|\s*$//g;
push @Members, $_->{'value'};
}
return undef;
});
if(!@Members){
$api->warn("Invalid medcom member table\n");
$api->whine("[[Wikipedia:Mediation Committee/Members]] cannot be processed", "The MedCom Member List table didn't seem to contain any members.", Pagename => 'Wikipedia talk:Mediation Committee/Bot issues');
return 60;
}
$api->store->{'Members revid'}=$Members_revid;
$api->store->{'Members'}=\@Members;
}
# Load the templates used to attract the bot
my %templates=$api->redirects_to_resolved('Template:Accepted case', 'Template:Rejected case');
if(exists($templates{''})){
$api->warn("Failed to get medcom template redirects: ".$templates{''}{'error'}."\n");
return 60;
}
# Fix all pages using these templates
my $iter=$api->iterator(
generator => 'embeddedin',
geititle => ['Template:Accepted case', 'Template:Rejected case'],
geinamespace => 4,
geifilterredir => 'nonredirects',
geilimit => 'max',
);
while(my $p=$iter->next){
return 0 if $api->halting;
if(!$p->{'_ok_'}){
$api->warn("Failed to retrieve transclusions for ".$iter->iterval.": ".$p->{'error'}."\n");
return 60;
}
my $title=$p->{'title'};
next if $title=~m{^Wikipedia:Requests for mediation/Rejected/\d+$};
next unless $title=~m{^Wikipedia:Requests for mediation/(.+)$};
my $subject=$1;
next if $subject eq 'Pending' || $subject eq 'Rejected cases' || $subject eq 'Tasks';
my $tok=$api->edittoken($title, EditRedir=>1);
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");
return 60;
}
my $intxt=$tok->{'revisions'}[0]{'slots'}{'main'}{'*'};
# Remove template
my $outtxt=$api->process_templates($intxt, sub {
my $name=shift;
return (($templates{"Template:$name"}//'') eq $iter->iterval)?'':undef;
});
# Sanity check
if($outtxt eq $intxt){
my $t=$iter->iterval; $t=~s/^Template://;
$api->whine("Cannot find MedCom template in [[$title]]", "I cannot find {{tl|$t}} in [[$title]], which probably means its transcluded in some odd manner. Please correct the case or fix me.", Pagename => 'Wikipedia talk:Mediation Committee/Bot issues');
next;
}
# Find the most recent MedCom editor to edit
my ($revid,$user,$ts,$txt);
if(grep $_ eq $tok->{'revisions'}[0]{'user'}, @Members){
$revid=$tok->{'revisions'}[0]{'revid'};
$user=$tok->{'revisions'}[0]{'user'};
$ts=$tok->{'revisions'}[0]{'timestamp'};
$txt=$tok->{'revisions'}[0]{'slots'}{'main'}{'*'};
} else {
$res=$api->query(
titles => $title,
prop => 'revisions',
rvprop => 'ids|user|timestamp',
rvlimit => 'max',
);
foreach my $r (@{(values %{$res->{'query'}{'pages'}})[0]{'revisions'}}){
last if $r->{'user'} eq $botname;
next unless grep $_ eq $r->{'user'}, @Members;
$revid=$r->{'revid'};
$user=$r->{'user'};
$ts=$r->{'timestamp'};
last;
}
if(!defined($revid)){
my $t=$iter->iterval; $t=~s/^Template://;
$api->whine("Problem in [[$title]]", "While I found {{tl|$t}} in [[$title]], I cannot find any edits by a member of MedCom. Something screwy is going on, or else I'm just broken. Please correct the case or fix me.", Pagename => 'Wikipedia talk:Mediation Committee/Bot issues');
next;
}
$res=$api->query(
revids => $revid,
prop => 'revisions',
rvprop => 'content',
rvslots => 'main',
);
$txt=(values %{$res->{'query'}{'pages'}})[0]{'revisions'}[0]{'slots'}{'main'}{'*'};
my $outtxt2=$api->process_templates($txt, sub {
my $name=shift;
return (($templates{"Template:$name"}//'') eq $iter->iterval)?'':undef;
});
# Sanity check
if($outtxt2 eq $txt){
my $t=$iter->iterval; $t=~s/^Template://;
$api->whine("Problem in [[$title]]", "While I found {{tl|$t}} in [[$title]], the most recent revision by a MedCom member did not contain the template. Something screwy is going on, or else I'm just broken. Please correct the case or fix me.", Pagename => 'Wikipedia talk:Mediation Committee/Bot issues');
next;
}
}
# Extract/construct sig
my $sig=undef;
if(!$sig){
my $t=strftime('%H:%M, %-d %B %Y \\(UTC\\)', gmtime ISO2timestamp($ts));
$sig=$1 if $txt=~/[fF]or the Mediation Committee,?\s+(.*?\Q$user\E.*?\s+$t)/;
}
if(!$sig){
my $t=strftime('%H:\\d{2}, %-d %B %Y \\(UTC\\)', gmtime ISO2timestamp($ts));
$sig=$1 if $txt=~/[fF]or the Mediation Committee,?\s+(.*?\Q$user\E.*?\s+$t)/;
}
if(!$sig){
my $t=strftime('\\d{2}:\\d{2}, %-d %B %Y \\(UTC\\)', gmtime ISO2timestamp($ts));
$sig=$1 if $txt=~/[fF]or the Mediation Committee,?\s+(.*?\Q$user\E.*?\s+$t)/;
}
if(!$sig){
my $t=strftime('%H:%M, %-d %B %Y (UTC)', gmtime ISO2timestamp($ts));
$sig="[[User:$user]] ([[User talk:$user|talk]]) $t";
}
# Find list of involved users
my @users=find_involved_users($api,$title,$intxt);
next unless @users;
# Build messages
my ($cat,$act);
if($iter->iterval eq 'Template:Accepted case'){
$act='accepted';
$cat='Category:Mediation Committee current cases';
$outtxt=$api->process_templates($outtxt, sub {
my $name=shift;
my $params=shift;
shift; # $wikitext
shift; # $data
my $oname=shift;
return undef unless $name eq "Medcombox";
my $ret="{{$oname";
my $done=0;
foreach ($api->process_paramlist(@$params)){
if($_->{"name"} eq "status"){
my $v=$_->{"value"};
$_->{"text"}=~s/\Q$v\E/mediator/;
$done=1;
}
$ret.="|".$_->{"text"};
}
$ret.="\n|status=mediator" unless $done;
$ret.="}}";
return $ret;
});
} elsif($iter->iterval eq 'Template:Rejected case'){
$act='rejected';
$cat='Category:Requests for mediation rejected requests';
}
my $msg="{{subst:User:MediationBot/\u$act message|case=$subject|signature=$sig}}";
# Adjust categorization
my $adj='removing template';
$adj='adjusting category' if $outtxt=~s/\[\[\s*(?i:Category)\s*:\s*(?:Mediation Committee (?:pending|current|rejected) cases|Requests for mediation rejected requests)\s*((?:\|.*?)?)\]\]/[[$cat$1]]/g;
$api->log("$title $act, $adj");
$res=$api->edit($tok, $outtxt, "Case $act, $adj. $screwup", 0, 0);
if($res->{'code'} ne 'success'){
$api->warn("Failed to edit $title: ".$res->{'error'}."\n");
return 60;
}
if($adj eq 'adjusting category'){
my $notify=$api->store->{'notify'};
foreach my $u (@users) {
$notify->{"$u|$title"}=[$u,$subject,$title,$act,"A request for mediation which you are a party to has been $act",$msg];
}
$api->store->{'notify'}=$notify;
}
}
# Update the pending listing page
{
return 0 if $api->halting;
my $tok=$api->edittoken('Wikipedia:Requests for mediation/Pending');
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 Wikipedia:Requests for mediation/Pending: ".$tok->{'error'}."\n");
return 60;
}
my $intxt=$tok->{'revisions'}[0]{'slots'}{'main'}{'*'};
my $outtxt=$intxt; $outtxt=~s/(<!--MEDBOT-Do-Not-Remove-Or-Change-This-Line-->).*/$1\n/s;
$iter=$api->iterator(
generator => 'categorymembers',
gcmtitle => 'Category:Mediation Committee pending cases',
gcmnamespace => 4,
gcmtype => 'page',
gcmlimit => 'max',
gcmsort => 'timestamp',
prop => 'info',
);
my $ct=0;
while(my $p=$iter->next){
if(!$p->{'_ok_'}){
$api->warn("Failed to retrieve members for Category:Mediation Committee pending cases: ".$p->{'error'}."\n");
return 60;
}
my $title=$p->{'title'};
next unless $title=~m{^Wikipedia:Requests for mediation/(.+)$};
my $subject=$1;
$outtxt.="{{$title}}\n";
$ct++;
# Notify users of newly-filed case
if(($api->store->{"new $title"}//0) != $p->{'lastrevid'}){
my $res2=$api->rawpage($title);
if($res2->{'code'} ne 'success'){
$api->warn("Failed to get content for $title: ".$res2->{'error'}."\n");
return 60;
}
my $txt=$res2->{'content'};
# Find list of involved users
my @users=find_involved_users($api,$title,$txt);
next unless @users;
# Build messages
my $msg="{{subst:User:MediationBot/Opened message|case=$subject}}";
# Queue notifications
my $notify=$api->store->{'notify'};
my $didnotify=$api->store->{'didnotify'};
foreach my $u (@users) {
next if grep $_ eq $u, @{$didnotify->{$title}};
$notify->{"opened|$u|$title"}=[$u,$subject,$title,'opened',"A request for formal mediation has been filed for a case in which you are involved",$msg];
push @{$didnotify->{$title}}, $u;
}
$api->store->{'notify'}=$notify;
$api->store->{'didnotify'}=$didnotify;
$api->store->{"new $title"}=$p->{'lastrevid'};
}
}
if($outtxt ne $intxt){
$api->log("Updating pending case list, $ct listed");
$res=$api->edit($tok, $outtxt, "Updating pending case list, $ct listed. $screwup", 0, 0);
if($res->{'code'} ne 'success'){
$api->warn("Failed to edit Wikipedia:Requests for mediation/Pending: ".$res->{'error'}."\n");
return 60;
}
}
}
my %q=(
list => 'categorymembers',
cmnamespace => 4,
cmtype => 'page',
cmlimit => 'max',
cmsort => 'timestamp',
cmprop => 'title|timestamp',
);
# Update the rejected listing page
{
return 0 if $api->halting;
my $tok=$api->edittoken('Wikipedia:Requests for mediation/Rejected cases', links=>{ namespace=>4 });
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 Wikipedia:Requests for mediation/Rejected cases: ".$tok->{'error'}."\n");
return 60;
}
my $intxt=$tok->{'revisions'}[0]{'slots'}{'main'}{'*'};
my @links=map $_->{'title'}, @{$tok->{'links'}};
my $outtxt=$intxt;
$iter=$api->iterator(%q, cmtitle => 'Category:Requests for mediation rejected requests');
my $ct=0;
my %skip=map { $_ => 1 } @{$api->store->{'processed rejected'} // []};
my %newskip=();
while(my $p=$iter->next){
if(!$p->{'_ok_'}){
$api->warn("Failed to retrieve members for Category:Requests for mediation rejected requests: ".$p->{'error'}."\n");
return 60;
}
my $title=$p->{'title'};
next unless $title=~m{^Wikipedia:Requests for mediation/(.+)$};
my $subject=$1;
$newskip{$subject}=1;
next if grep $title eq $_, @links;
next if exists($skip{$subject});
my $dt=strftime('%-d %B %Y', gmtime ISO2timestamp($p->{'timestamp'}));
$outtxt=~s/(<!--MEDBOT-Do-Not-Remove-Or-Change-This-Line-->)/===$subject===\n*[[$title]]\n:*Rejected $dt\n$1/s;
$ct++;
}
if($outtxt ne $intxt){
$api->log("Updating case list, +$ct rejected");
$res=$api->edit($tok, $outtxt, "Updating case list, +$ct rejected. $screwup", 0, 0);
if($res->{'code'} ne 'success'){
$api->warn("Failed to edit Wikipedia:Requests for mediation/Rejected cases: ".$res->{'error'}."\n");
return 60;
}
}
$api->store->{'processed rejected'}=[keys %newskip];
}
# Update the accepted listing page
{
return 0 if $api->halting;
my $tok=$api->edittoken('Wikipedia:Requests for mediation/Tasks', links=>{ namespace=>4 });
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 Wikipedia:Requests for mediation/Tasks: ".$tok->{'error'}."\n");
return 60;
}
my $intxt=$tok->{'revisions'}[0]{'slots'}{'main'}{'*'};
my @links=map $_->{'title'}, @{$tok->{'links'}};
my $outtxt=$intxt;
$iter=$api->iterator(%q, cmtitle => 'Category:Mediation Committee current cases');
my $ct_new_cases=0;
while(my $p=$iter->next){
if(!$p->{'_ok_'}){
$api->warn("Failed to retrieve members for Category:Mediation Committee current cases: ".$p->{'error'}."\n");
return 60;
}
my $title=$p->{'title'};
next unless $title=~m{^Wikipedia:Requests for mediation/(.+)$};
my $subject=$1;
next if grep $title eq $_, @links;
my $dt=strftime('%-d %b %Y', gmtime ISO2timestamp($p->{'timestamp'}));
$outtxt=~s/(?:\{\{Wikipedia:Requests for mediation\/Open Tasks\/None\}\}\n)?(<!--MEDBOT-Do-Not-Remove-Or-Change-This-Line-->)/{{Wikipedia:Requests for mediation\/Open Tasks\/U|$subject|$dt}}\n$1/s;
$ct_new_cases++;
}
$iter=$api->iterator(%q, cmtitle => 'Category:Mediation Committee Nominations/Pending');
my $ct_new_noms=0;
my $ct_rm_noms=0;
my %rmnoms=map { $_ => 1 } grep(m{^Wikipedia:Mediation Committee/Nominations/.+$}, @links);
while(my $p=$iter->next){
if(!$p->{'_ok_'}){
$api->warn("Failed to retrieve members for Category:Mediation Committee Nominations/Pending: ".$p->{'error'}."\n");
return 60;
}
my $title=$p->{'title'};
next unless $title=~m{^Wikipedia:Mediation Committee/Nominations/(.+)$};
next if $title eq 'Wikipedia:Mediation Committee/Nominations/Current';
my $subject=$1;
delete $rmnoms{$title};
next if grep $title eq $_, @links;
my $dt=strftime('%-d %b %Y', gmtime ISO2timestamp($p->{'timestamp'}));
$outtxt=~s/(?:\{\{Wikipedia:Requests for mediation\/Open Tasks\/None\}\}\n)?(<!--MEDBOT-Do-Not-Remove-Or-Change-This-Line-Nom-->)/{{Wikipedia:Requests for mediation\/Tasks\/N|$subject|$dt}}\n$1/s;
$ct_new_noms++;
}
if(%rmnoms){
$outtxt=$api->process_templates($outtxt, sub {
my $name=shift;
my $params=shift;
return undef if $name ne 'Wikipedia:Requests for mediation/Tasks/N';
foreach ($api->process_paramlist(@$params)){
$name="Wikipedia:Mediation Committee/Nominations/".$_->{'value'} if $_->{'name'} eq '1';
}
return undef unless exists($rmnoms{$name});
$ct_rm_noms++;
return '';
});
}
my $rmnone=0;
for my $in ($outtxt=~/\|-((?:[^!]|(?><!--.*?-->))*<!--MEDBOT-Do-Not-Remove-Or-Change-This-Line(?:|-Nom)-->(?:[^!]|(?><!--.*?-->))*)(?=\n!)/g){
my $any=0;
my $out=$api->process_templates($in, sub {
my $name=shift;
return '' if $name eq "Wikipedia:Requests for mediation/Tasks/None";
$any=1 if $name=~/Wikipedia:Requests for mediation\//;
return undef;
});
if($any && $out ne $in){
$outtxt=~s/\Q$in\E/$out/g;
$rmnone=1;
}
}
my $addnone=0;
for my $in ($outtxt=~/\|-\n! colspan="7".*\n((?:[^!]|(?><!--.*?-->))*)(?=\n\|-\n[!|] colspan="7")/g){
my $any=0;
$api->process_templates($in, sub {
my $name=shift;
$any=1 if $name=~/Wikipedia:Requests for mediation\//;
return undef;
});
if(!$any){
$outtxt=~s/\Q$in\E/$in\n{{Wikipedia:Requests for mediation\/Tasks\/None}}/g;
$addnone=1;
}
}
if($outtxt ne $intxt){
my @summary=();
push @summary, "updating case list, +$ct_new_cases accepted" if $ct_new_cases;
push @summary, "updating nominations list".($ct_new_noms?", +$ct_new_noms current":"").($ct_rm_noms?", -$ct_rm_noms completed":"") if($ct_new_noms || $ct_rm_noms);
push @summary, "removing unneeded \"Currently none\"" if $rmnone;
push @summary, "adding needed \"Currently none\"" if $addnone;
unless(@summary){
$api->warn("No summary for changes to Wikipedia:Requests for mediation/Tasks!");
return 60;
}
my $summary=join('; ', @summary);
$summary="\u$summary";
$api->log($summary);
$res=$api->edit($tok, $outtxt, "$summary. $screwup", 0, 0);
if($res->{'code'} ne 'success'){
$api->warn("Failed to edit Wikipedia:Requests for mediation/Tasks: ".$res->{'error'}."\n");
return 60;
}
}
}
# Update the pending nominations page
{
return 0 if $api->halting;
my $tok=$api->edittoken('Wikipedia:Mediation Committee/Nominations/Current');
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 Wikipedia:Mediation Committee/Nominations/Current: ".$tok->{'error'}."\n");
return 60;
}
my $intxt=$tok->{'revisions'}[0]{'slots'}{'main'}{'*'};
my $outtxt=$intxt; $outtxt=~s/(<!--MEDBOT-Do-Not-Remove-Or-Change-This-Line-->).*/$1\n/s;
$iter=$api->iterator(%q, cmtitle => 'Category:Mediation Committee Nominations/Pending');
my $ct=0;
while(my $p=$iter->next){
if(!$p->{'_ok_'}){
$api->warn("Failed to retrieve members for Category:Mediation Committee Nominations/Pending: ".$p->{'error'}."\n");
return 60;
}
my $title=$p->{'title'};
next unless $title=~m{^Wikipedia:Mediation Committee/Nominations/(.+)$};
next if $title eq 'Wikipedia:Mediation Committee/Nominations/Current';
$outtxt.="{{$title}}\n";
$ct++;
}
if($outtxt ne $intxt){
$api->log("Updating nominations list, $ct listed");
$res=$api->edit($tok, $outtxt, "Updating nominations list, $ct listed. $screwup", 0, 0);
if($res->{'code'} ne 'success'){
$api->warn("Failed to edit Wikipedia:Mediation Committee/Nominations/Current: ".$res->{'error'}."\n");
return 60;
}
}
}
my $notify=$api->store->{'notify'};
foreach my $k (keys %$notify) {
return 0 if $api->halting;
my ($user,$subject,$title,$act,$summary,$msg)=@{$notify->{$k}};
my $tok=$api->edittoken("User talk:$user");
if($tok->{'code'} eq 'shutoff'){
$api->warn("Task disabled: ".$tok->{'content'}."\n");
return 300;
}
if($tok->{'code'} eq 'pageprotected' || $tok->{'code'} eq 'botexcluded'){
# Cannot notify, don't worry about it
delete $notify->{$k};
my $cannotnotify=$api->store->{'cannotnotify'}//{};
push @{$cannotnotify->{$title}}, $user;
$api->store->{'notify'}=$notify;
$api->store->{'cannotnotify'}=$cannotnotify;
next;
}
if($tok->{'code'} ne 'success'){
$api->warn("Failed to get edit token for User talk:$user: ".$tok->{'error'}."\n");
next;
}
my $txt=$tok->{'revisions'}[0]{'slots'}{'main'}{'*'}//'';
if($act eq 'opened' && $txt=~/<!---MedComBot-Do-not-remove-this-line-Notified-\Q$subject\E--->/){
$api->log("It seems $user is already notified of $act request, skipping");
} else {
$txt=~s/\s*$/\n\n$msg/;
$api->log("Notifying $user of $act request");
$res=$api->edit($tok, $txt, $summary, 0, 0);
if($res->{'code'} ne 'success'){
$api->warn("Failed to edit User talk:$user: ".$res->{'error'}."\n");
next;
}
}
delete $notify->{$k};
$api->store->{'notify'}=$notify;
}
my $cannotnotify=$api->store->{'cannotnotify'}//{};
foreach my $title (keys %$cannotnotify) {
return 0 if $api->halting;
my @users=@{$cannotnotify->{$title}};
my $ttitle=$title; $ttitle=~s/^Wikipedia:/Wikipedia talk:/;
my $tok=$api->edittoken($ttitle);
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 $ttitle: ".$tok->{'error'}."\n");
next;
}
my $txt=$tok->{'revisions'}[0]{'slots'}{'main'}{'*'}//'';
$txt=~s/\s+$//;
$txt.="\n\n" if $txt ne '';
$txt.="== Involved users who cannot be notified ==\n{{ClerkNote}} The following users could not be notified due to page protection or bot exclusion:\n".join("\n", map "* {{user|$_}}", @users)."\nPlease notify them manually, or take other appropriate action. ~~~~\n";
$api->log("Noting users who cannot be notified");
$res=$api->edit($tok, $txt, "Noting users who cannot be notified. $screwup", 0, 0);
if($res->{'code'} ne 'success'){
$api->warn("Failed to edit $ttitle: ".$res->{'error'}."\n");
} else {
delete $cannotnotify->{$title};
$api->store->{'cannotnotify'}=$cannotnotify;
}
}
return 3600;
}
sub find_involved_users {
my ($api,$title,$txt) = @_;
my $userre = qr/\{\{[Uu]ser\|\s*([^\s\x7c\x7d](?:[^\x7c\x7d]*?[^\s\x7c\x7d]))\s*\}\}/;
$txt=~s/\n::<span style="font-size: 95%;">\{\{Red\|'''Filing party'''\}\}:.*//;
unless($txt=~/\n(?:; (?:Involved users|(?:Users|Editors) involved in (?:this )?dispute)|===\s*Involved parties\s*===)\s*\n((?:#\s*${userre}[^\n{}]*\n(?:#[:*][^\n{}]*\n)*)+)\s*(?:;|==|<!-- end user list -->)/){
$api->warn("Cannot find involved users list in $title");
$api->whine("Cannot find involved users list in [[$title]]", "I cannot find the list of involved users in [[$title]]; I look for the line \"; Editors involved in this dispute\", followed by an ordered list (lines beginning \"#\") with each list entry beginning with the {{tl|user}} template, followed by a new section (a line beginning \"==\"), subsection (a line beginning \";\"), or the special comment \"<code><nowiki><!-- end user list --></nowiki></code>\". Please correct the case or fix me.", Pagename => 'Wikipedia talk:Mediation Committee/Bot issues');
return ();
}
return map ucfirst($_), ($1=~/$userre/g);
}
1;