User:AnomieBOT/source/tasks/PERTableUpdater.pm: Difference between revisions

Content deleted Content added
AnomieBOT (talk | contribs)
Updating published sources: PERTableUpdater * Update for gerrit:223440.
AnomieBOT (talk | contribs)
Updating published sources: PERTableUpdater: * Use {{tl|v}} to generate view and history links.
 
(25 intermediate revisions by 4 users not shown)
Line 14:
 
Update [[User:AnomieBOT/PERTable]], [[User:AnomieBOT/TPERTable]],
[[User:AnomieBOT/SPERTableEPERTable]], and [[User:AnomieBOT/EDITREQTableSPERTable]].,
[[User:AnomieBOT/COIREQTable]], and [[User:AnomieBOT/PREQTable]].
 
=end metadata
Line 30 ⟶ 31:
@ISA=qw/AnomieBOT::Task/;
 
my %colors=(
'red' => ' style="background-color:#ffbfdc"',
'yellow' => ' style="background-color:#fff9bf"',
'green' => ' style="background-color:#e4ffcc"',
'clear' => '',
);
my %protact=(
'modify' => 'Modified',
Line 81 ⟶ 76:
}
if(($api->store->{"ver"}//1) < 2){
for my $tag (qw/PER TPER SPER EDITREQ/) {
next unless exists($api->store->{"$tag pages"});
my %old = %{$api->store->{"$tag pages"}};
my %new = ();
while(my ($k,$v) = each %old) {
$new{$k}{$v->{'talk'}} = $v if exists($v->{'talk'});
}
$api->store->{"$tag pages"} = \%new;
}
$api->store->{"ver"} = 2;
}
 
# Flush warnings daily
my $ts = time;
$ts -= $ts % 86400;
if ( ($api->store->{'warnedBadRegexDate'} // 0) < $ts) {
$api->store->{'warnedBadRegex'} = {};
$api->store->{'warnedBadRegexDate'} = $ts;
}
 
Line 103 ⟶ 106:
for my $source (@sources) {
my ($i, $name, $page) = @$source;
my $tb=$api->rawpage($page);
if ( $page=~/^meta:(.+)$/ ) {
$tb=$api->copy( wikibase => 'https://meta.wikimedia.org/w/', assert => 'user' )->rawpage( $1 );
} else {
$tb=$api->rawpage($page);
}
if($tb->{'code'} ne 'success'){
$api->warn("Failed to load $page: ".$tb->{'error'}."\n");
return 60;
}
my $ln = 0;
for my $line (split /\r?\n/, $tb->{'content'}){
$ln++;
my $re=$line;
my %opts=();
Line 126 ⟶ 136:
$re="(?-i:$re)" if($opts{'casesensitive'}//0);
 
$re=~s!(\{\{\s*ns\s*:\s*(.+?)\s*\}\})! replace_ns($api,$2) // $1 !ge;
 
# Try to escape left-braces that aren't quantifiers or parameters to escapes
my $tmp = $re;
$re=~s#(?<!\\[a-zA-Z])(?<!\\)\{(?!\d+(?:,\d*)?})#\\{#g;
$self->warnBadRegex( $api, "$page:$ln: Escaped left-braces in regex (old): $tmp" ) if $tmp ne $re;
$self->warnBadRegex( $api, "$page:$ln: Escaped left-braces in regex (new): $re" ) if $tmp ne $re;
 
# Validate each line, in case someone screws up the blacklist page
eval {
no warnings;
qr/^(?:$re)$/si;
};
if ( $@ ) {
$self->warnBadRegex( $api, "$page:$ln: Ignoring bad regex '$re': $@\n");
next;
}
 
# Log non-fatal warnings too.
eval {
use warnings FATAL => 'all';
qr/^(?:$re)$/si;
};
if ( $@ ) {
$self->warnBadRegex( $api, "$page:$ln: Warning: $@\n");
}
 
# Let's just hope no one ever uses {{int:}} here...
Line 140 ⟶ 175:
 
# Fields are:
# 0: Namespaces to color green"attention" instead of clear"normal"
# 1: "Tag", also used in the name of the subpage the table is put on
# 2: Category name, no prefix
Line 146 ⟶ 181:
# 4: URL fragment for request links
# 5: NID component of the urn links
# 6: List of colorscolor-classes to apply based on page protection level:
# 0: unprotected
# 1: semi-protected
# 2: semi-protected via title blacklist
# 3: templateextended-confirmed protected
# 4: Usertemplate CSS/JS pageprotected
# 5: fullyUser protectedJSON page
# 6: "fully"User protectedCSS/JS via title blacklistpage
# 7: cascadingfully protectionprotected
# 8: MediaWiki-namespace"fully" pageprotected via title blacklist
# 9: cascading protection
# 10: MediaWiki-namespace page
# 11: MediaWiki-namespace CSS/JS page
my @data=(
[[10,828],'PER','Wikipedia fully- protected edit requests','protected','editprotected','x-wp-editprotected',[qw/rederror error error error rederror rednormal rederror yellownormal clearcaution yellowcaution yellowcaution yellowerror/]],
[[10,828],'TPER','Wikipedia template-protected edit requests','template-protected','edittemplateprotected','x-wp-edittemplateprotected',[qw/rederror rederror rederror clearerror rednormal rederror yellowerror rederror redcaution error error error/]],
[[10,828],'SPEREPER','Wikipedia semiextended-confirmed-protected edit requests','semiextended-confirmed-protected','editsemiprotectededitextendedprotected','x-wp-editsemiprotectededitextendedprotected',[qw/rederror error error normal clearerror yellowerror rederror rederror rederror rederror rederror rederror/]],
[[010,828],'EDITREQSPER','RequestedWikipedia editssemi-protected edit requests','COIsemi-protected','requestediteditsemiprotected','x-wp-requestediteditsemiprotected',[qw/clearerror normal caution error error yellowerror yellowerror rederror rederror rederror rederror rederror/]],
[[],'IPER','Wikipedia interface-protected edit requests','interface-protected','editinterfaceprotected','x-wp-editinterfaceprotected',[qw/error error error error error error normal error error error error normal/]],
[[0],'COIREQ','Wikipedia conflict of interest edit requests','COI','requestedit','x-wp-requestedit',[qw/normal caution caution caution error error error error error error error error/]],
[[],'PREQ','Wikipedia partial-block edit requests','partial block','editpartiallyblocked','x-wp-editpartiallyblocked',[qw/normal caution caution caution error error error error error error error error/]],
);
my $starttime=time;
for my $data (@data){
my ($greennsattentionns,$tag,$cat,$type,$tgt,$urn,$colors)=@$data;
my $iter=$api->iterator(
generator => 'categorymembers',
Line 209 ⟶ 250:
touched => ISO2timestamp($p->{'touched'}),
});
$pages{$t}{$tt}{'reqisredir'} = defined( $p->{'redirect'} );
delete $pages{$t}{$tt}{'color'};
delete $pages{$t}{$tt}{'prottype'};
Line 216 ⟶ 258:
}
$api->store->{"$tag pages"}=\%pages;
$api->store->{"ver"} = 2;
 
if(%pages){
Line 233 ⟶ 276:
 
# Protection scoring "bitmap":
# 0x2000x8000 = MediaWiki-namespace CSS/JS auto-protection
# 0x1000x4000 = CascadingMediaWiki-namespace auto-protection
# 0x800x2000 = FullCascading protection
# 0x400x1000 = User scriptFull auto-protection
# 0x200x100 = TemplateUser script auto-protection
# 0x10 0x80 = SemiUser JSON auto-protection
# 0x08 0x40 = DirectlyTemplate-applied protection
# 0x02 =0x20 Title= blacklistExtended-confirmed protection
# 0x10 = Semi-protection
# 0x08 = Directly-applied protection
# 0x02 = Title blacklist protection
# Highest score by int value "wins".
my $protscore=0;
$pd->{'prottype'}='Not protected';
$pd->{'reason'}='';
if($p->{'ns'}==8 && ($p->{'contentmodel'} eq 'javascript' || $t=~m!\.js$!)){
$pd->{'prottype'}='Site JS page';
$pd->{'color'}=$colors->[4] if( $protscore & 0x40)=0xc000;
} elsif($p->{'ns'}==8 && ($p->{'contentmodel'} eq 'css' || $t=~m!\.css$!)){
$pd->{'prottype'}='Site CSS page';
$protscore=0xc000;
} elsif($p->{'ns'}==8){
$pd->{'prottype'}='MediaWiki page';
$protscore=0x2000x4000;
} elsif($p->{'ns'}==2 && ($p->{'contentmodel'} eq 'javascript' || $t=~m!/.*\.js$!)){
$pd->{'prottype'}='User JS page';
$protscore=0x400x100;
} elsif($p->{'ns'}==2 && ($p->{'contentmodel'} eq 'css' || $t=~m!/.*\.css$!)){
$pd->{'prottype'}='User CSS page';
$protscore=0x400x100;
} elsif($p->{'ns'}==2 && ($p->{'contentmodel'} eq 'json' || $t=~m!/.*\.json$!)){
$pd->{'prottype'}='User JSON page';
$protscore=0x80;
}
 
Line 264 ⟶ 319:
}
if ( $tb && $tb->{'source'} ) {
my $sc=exists($tb->{'opts'}{'autoconfirmed'})?0x12:0x220x42;
next if $sc<$protscore;
$pd->{'prottype'}=$tb->{'source'};
my $line=$tb->{'line'};
$pd->{'reason'}=qq(Matching line: <syntaxhighlight lang="text" enclose="none"inline>$line</syntax).qq(highlight>);
$protscore=$sc;
}
Line 278 ⟶ 333:
next unless $pp->{'type'} eq $prottype;
my $sc=0;
$sc|=0x800x1000 if $pp->{'level'} eq 'sysop';
$sc|=0x200x40 if $pp->{'level'} eq 'templateeditor';
$sc|=0x20 if $pp->{'level'} eq 'extendedconfirmed';
$sc|=0x10 if $pp->{'level'} eq 'autoconfirmed';
$sc|=exists($pp->{'source'})?0x1000x2000:0x08;
$sc|=0x1000x2000 if exists($pp->{'cascade'});
next if $sc<$protscore;
if(exists($pp->{'source'})){
Line 291 ⟶ 347:
$pd->{'prottype'}='Fully protected' if $pp->{'level'} eq 'sysop';
$pd->{'prottype'}='Template-protected' if $pp->{'level'} eq 'templateeditor';
$pd->{'prottype'}='Extended-confirmed protected' if $pp->{'level'} eq 'extendedconfirmed';
$pd->{'prottype'}='Semiprotected' if $pp->{'level'} eq 'autoconfirmed';
$pd->{'prottype'}.=' with cascading' if exists($pp->{'cascade'});
Line 304 ⟶ 361:
$pd->{'color'}=$colors->[2] if($protscore & 0x02);
}
$pd->{'color'}=$colors->[3] if($protscore & 0x20){;
$pd->{'color'}=$colors->[3] if($protscore & 0x200x40);{
$pd->{'color'}=$colors->[64] if($protscore & 0x020x40);
$pd->{'color'}=$colors->[8] if($protscore & 0x02);
}
$pd->{'color'}=$colors->[4] if($protscore & 0x40);
$pd->{'color'}=$colors->[5] if($protscore & 0x80);
$pd->{'color'}=$colors->[76] if($protscore & 0x100);
$pd->{'color'}=$colors->[87] if($protscore & 0x2000x1000);
$pd->{'color'}='green'$colors->[9] if($pd->{'color'} eq 'clear'protscore && grep($p->{'ns'}==$_, @$greenns)0x2000);
$pd->{'color'}=$colors->[10] if($protscore & 0x4000);
$pd->{'color'}=$colors->[11] if($protscore & 0x8000);
$pd->{'color'}='attention' if($pd->{'color'} eq 'normal' && grep($p->{'ns'}==$_, @$attentionns));
 
if($pd->{'reason'} eq ''){
Line 345 ⟶ 405:
}
$pd->{'logtitle'}=$pg;
$pd->{'isredir'}=defined( $p->{'redirect'} );
 
# now fill in the rest
Line 356 ⟶ 417:
# The formatting here is a little strange, for backwards compat
my @pages=map { values %$_ } values %pages;
my $txt = qq(<div class="veblenbot-pertable"noinclude>{{User:AnomieBOT/PERTableHeader}}</noinclude>\n);
$txt.=qq(<div class="veblenbot-pertable">\n);
$txt.=qq(<templatestyles src="Template:Edit_fully-protected/color_legend/styles.css"/>\n);
$txt.=qq({| class="wikitable" style="padding:0em"\n);
$txt.=qq(|-\n);
Line 362 ⟶ 425:
my $s=($ct==1?'':'s');
my $pg='User:AnomieBOT/'.$tag.'Table';
$txt.=qq(! <section begin="count" />$ct<section end="count" /> [[:Category:$cat|$type edit request$s]] <div {{v|$pg|h|style="float:right;white-space:nowrap">[[$pg|v]]&middot;<span class="plainlinks">[//en.wikipedia.org/w/index.php?title=$pg&action=history h]</span></div>}}\n);
$txt.=qq(|-\n);
$txt.=qq(|\n);
Line 370 ⟶ 433:
$txt.=qq(! Protection level\n);
$txt.=qq(! class = "unsortable" | Last protection log entry\n);
for my $p (sort { my $x = $a->{'touched'} <=> $b->{'touched'}; $x = $a->{'title'} cmp $b->{'title'} if $x == 0; return $x; } @pages){
my $c=$colors{$p->{'color'}};
my $t=$p->{'title'};
my $et=encodetitle($p->{'logtitle'});
Line 377 ⟶ 440:
my $pt=$p->{'prottype'};
my $r=$p->{'reason'};
my $txt.tl =qq(| $p->{'isredir'} ? "{{-r|1=$t}}" : "[[:$c\n)t]]";
my $txt.ttl =qq( $p->{'reqisredir'} ? "{{-r|1=$tt#$tgt|2=request}}" [[:$t]] ("[[$tt#$tgt|request]])\n)";
$txt.=qq(|- class="protectededit-legend-$c"\n);
$txt.=qq(| $tl ($ttl)\n);
$txt.=strftime("| %F %H:%M\n", gmtime $p->{'touched'});
$txt.=qq(| $pt <span class="plainlinks">([//en.wikipedia.org/w/index.php?title=Special:Log&type=protect&page=$et log])</span>\n);
Line 397 ⟶ 462:
next;
}
my $intxt=$tok->{'revisions'}[0]{'slots'}{'main'}{'*'}//'';
$intxt=~s/^\s+|\s+$//;
$intxt=~s#<!--TS-->.*<!--/TS-->#<!--TS-->~~~~~<!--/TS-->#g;
Line 412 ⟶ 477:
$t=0 if $t<0;
return $t;
}
 
sub warnBadRegex {
my ($self, $api, $msg) = @_;
 
$msg =~ s/\s+$//;
my $file = __FILE__;
$msg =~ s/ at \Q$file\E line \d+\.$//;
 
if ( ! defined( $api->{'noedit'} ) ) {
my $warned = $api->store->{'warnedBadRegex'};
return if exists( $warned->{$msg} );
$warned->{$msg} = 1;
$api->store->{'warnedBadRegex'} = $warned;
}
 
$api->warn( "$msg\n" );
}