User:HBC AIV helperbot/source: Difference between revisions
Appearance
Content deleted Content added
cleanup |
Added {{userlinks|user}} recognition |
||
Line 90: | Line 90: | ||
foreach my $line (@content) |
foreach my $line (@content) |
||
{ |
{ |
||
($line =~ m/vandal\|\s*(.*?)\s*\}\}/i) || next(); # Go to next line if there is not a vandal template on this one. |
($line =~ m/(vandal|userlinks)\|\s*(.*?)\s*\}\}/i) || next(); # Go to next line if there is not a vandal template on this one. |
||
my $user = $ |
my $user = $2; # Extract username from template |
||
next if ($user eq 'username'); # Skip the examples {{vandal|username}} {{ipvandal|username}} |
next if ($user eq 'username'); # Skip the examples {{vandal|username}} {{ipvandal|username}} {{userlinks|username}} |
||
$report_count++; |
$report_count++; |
||
add_job([\&check_user,$c,$user,$page],0) if (lc($remove_blocked) eq 'on'); # Queue a check_user job for the user to run ASAP |
add_job([\&check_user,$c,$user,$page],0) if (lc($remove_blocked) eq 'on'); # Queue a check_user job for the user to run ASAP |
||
Line 198: | Line 198: | ||
{ |
{ |
||
my $line = shift(@content); |
my $line = shift(@content); |
||
unless ($line =~ m/vandal\|\s*$re_user\s*\}\}/i) |
unless ($line =~ m/(userlinks|vandal)\|\s*$re_user\s*\}\}/i) |
||
{ |
{ |
||
push(@new_content,$line); |
push(@new_content,$line); |
||
next if ($line =~ m/vandal\|username/); |
next if ($line =~ m/(userlinks|vandal)\|username/i); |
||
if($line =~ m/\{\{IPvandal\|/i) |
if($line =~ m/\{\{IPvandal\|/i) |
||
{ |
{ |
||
$ips_left++; |
$ips_left++; |
||
} |
} |
||
elsif($line =~ m/\{\{vandal\|/i) |
elsif($line =~ m/\{\{(userlinks|vandal)\|/i) |
||
{ |
{ |
||
$users_left++; |
$users_left++; |
||
Line 214: | Line 214: | ||
{ |
{ |
||
$found = 1; |
$found = 1; |
||
while ((scalar(@content)) && !($content[0] =~ m/\{\{I?P?vandal\|/i)) |
while ((scalar(@content)) && !($content[0] =~ m/\{\{(userlinks|I?P?vandal)\|/i)) |
||
{ |
{ |
||
my $removed = shift(@content); |
my $removed = shift(@content); |
Revision as of 20:52, 22 January 2007
This source is released under GFDL. Enjoy.
Note This code uses a version of the MediaWiki module that I repaired, all official versions are not functioning with the current mediawiki servers, so I fixed it. If you wish to reproduce this script you can e-mail me for the repaired mediawiki.pm file. HighInBC (Need help? Ask me) 03:37, 3 January 2007 (UTC)
use strict; use MediaWiki; use URI::Escape; use Time::Local; my $VERSION = 'HBC AIV helperbot v1.2.5 - Testing'; my $read_rate = 10; my $write_rate = 10; my(@pages_to_watch) = ( 'Wikipedia:Administrator intervention against vandalism', 'Wikipedia:Administrator intervention against vandalism/TB2', ); open(PASS,'password'); # A file with only the password, no carraige return sysread(PASS, my $password, -s(PASS)); # No password in sourcecode. close(PASS); my $c = MediaWiki->new; $c->setup ({ 'bot' => {'user' => 'HBC AIV helperbot','pass' => $password}, 'wiki' => {'host' => 'en.wikipedia.org','path' => 'w'} }) || die "Failed to log in\n"; my $whoami = $c->user(); warn "$whoami connected\n"; # The program runs in this loop which handles a queue of jobs. my(@job_list); my $timing = 0; foreach my $page (@pages_to_watch) { add_job([\&check_page,$c,$page],$timing); $timing += 5; } while (1) # Infinite loop, a serpent biting it's own tail. { sleep(1); # Important in all infinite loops to keep it calm my (@kept_jobs); # A place to put jobs not ready to run yet while (my $job = shift(@job_list)) # Go through each job pending { my($r_job , $timing) = @{$job}; if ($timing < time()) # If it is time to run it then run it { if (ref($r_job) eq 'ARRAY') # Callback style, reference an array with a sub followed by paramaters { my $cmd = shift(@{$r_job}); &{$cmd}(@{$r_job}); } elsif (ref($r_job) eq 'CODE') # Otherwise just the reference to the sub { &{$r_job}; } } else # If it is not time yet, save it for later { push(@kept_jobs , $job) } } push (@job_list , @kept_jobs); # Keep jobs that are still pending } sub add_job # Command to add a job to the queue { my ($r_job , $timing) = @_; push (@job_list , [$r_job , (time()+$timing)]); } sub check_page # Read the page and gather usernames, give each use a check_user job on the queue { # Then add Check_page to the queue scheduled for $read_rate seconds my $c = shift; my $page = shift; add_job([\&check_page,$c,$page],$read_rate); # Schedule myself $read_rate seconds later my ($report_count); # Get page, read only my $content = $c->get($page, 'r')->{'content'}; unless ($content =~ m|\{\{(n?o?adminbacklog)\}\} <\!-- RemoveBlocked=([^ ]+) AutoBacklog=([^ ]+) AddLimit=(\d+) RemoveLimit=(\d+) -->|i) { warn "Could not find paramater string, not doing anything: $page\n"; next; } my($ab_current, $remove_blocked, $auto_backlog, $ab_add,$ab_remove) = ($1,$2,$3,$4,$5); ($auto_backlog = undef) if ($ab_add <= $ab_remove); my @content = split("\n",$content); # Split into lines foreach my $line (@content) { ($line =~ m/(vandal|userlinks)\|\s*(.*?)\s*\}\}/i) || next(); # Go to next line if there is not a vandal template on this one. my $user = $2; # Extract username from template next if ($user eq 'username'); # Skip the examples {{vandal|username}} {{ipvandal|username}} {{userlinks|username}} $report_count++; add_job([\&check_user,$c,$user,$page],0) if (lc($remove_blocked) eq 'on'); # Queue a check_user job for the user to run ASAP } if (lc($auto_backlog) eq 'on') { add_job([\&set_backlog,$c,$page,$report_count,$ab_add,$ab_remove],0) if ((($report_count >= $ab_add) && ($ab_current eq 'noadminbacklog')) || (($report_count <= $ab_remove) && ($ab_current eq 'adminbacklog'))); } return; } sub set_backlog { my ($c, $page_name, $report_count,$ab_add,$ab_remove) = @_; $report_count ||= '0'; my $page = $c->get($page_name, 'rw'); # Get page read/write my(@content) = split("\n",$page->{'content'}); # Split into lines my(@new_content); # Place to put replacement content foreach my $line (@content) { if ($line =~ m|\{\{n?o?adminbacklog\}\} <\!-- RemoveBlocked=[^ ]+ AutoBacklog=[^ ]+ AddLimit=\d+ RemoveLimit=\d+ -->|i) { if ($report_count >= $ab_add) { warn "Backlog added from: $page_name\n"; $page->{'summary'} = 'Noticeboard is backlogged. '.$report_count.' reports need attention.'; $line =~ s|\{\{noadminbacklog|\{\{adminbacklog|i; push (@new_content,$line); } elsif ($report_count <= $ab_remove) { warn "Backlog removed from: $page_name\n"; $page->{'summary'} = 'Noticeboard is no longer backlogged. '.$report_count.' reports need attention.'; $line =~ s|\{\{adminbacklog|\{\{noadminbacklog|i; push (@new_content,$line); } } else { push(@new_content,$line); } } $page->{'content'} = join("\n",@new_content); return unless($page->{'content'}); $page->save(); } sub check_user # Determine if the user is blocked, if so gather information about the block { # and shedule a remove_name job with all the information passed along my $c = shift; my $user = shift; # Username passed from check_page my $page = shift; my $url = $c->{index}.'?title=Special:Ipblocklist&ip='.uri_escape($user); my $data = $c->{ua}->get($url)->content(); # Get blocklist info for user if ($data =~ m|</a>\) blocked <a href|) # If the user is currently blocked { # Get name of blocking admin ($data =~ m|\d{2}, <a href="/wiki/User:(.*?)" title=|) || ($data =~ m|\d{2}, <a href="/w/index\.php\?title=User:(.*?)&|); #" my $blocker = uri_unescape($1); # Get expiry time of block, starting time of block, and calculate total time my $duration; if ($data =~ m|expires (\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})|) # Match expiry time if one exists { my $expiry = timegm($6,$5,$4,$3,$2-1,$1); # Parse expiry time $data =~ (m|<ul><li>(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}),|); # Match starting time my $block_time = timegm($6,$5,$4,$3,$2-1,$1); # Parse starting time $duration = timeconv($expiry - $block_time); # Pretty print the difference via timeconv (see below) } elsif($data =~ m|infinite|) # If there is no expiry and the word 'infinite' is found { $duration = 'indef'; # Set to indef } # Get block type flags my(@flags); (push(@flags,'AO')) if ($data =~ m|anon\. only|); # Match anon only (push(@flags,'ACB')) if ($data =~ m|account creation blocked|); # Match account creation blocked (push(@flags,'ABD')) if ($data =~ m|autoblock disabled|); # Match autoblock disabled my $block_type; # Build empty string # If any flag exists build a flag string. $block_type = '[[User:HBC AIV helperbot/Legend|('.join(' ',@flags).')]]' if (scalar(@flags)); add_job([\&remove_name,$c,$user,$blocker,$duration,$block_type,$page],0); # Queue a remove_name job to run ASAP } } sub remove_name { my $c = shift; my $user = shift; #|Passed from check_user my $blocker = shift; #| my $duration = shift; #| my $block_type = shift; #| my $page_name = shift; my $re_user = $user; $re_user =~ s|[\$\@]|.|g; my $page = $c->get($page_name, 'rw'); # Get page read/write my($ips_left,$users_left) = ('0','0'); # Start these with 0 instead of undef my(@content) = split("\n",$page->{'content'}); # Split into lines my(@new_content); # Place to put replacement content my $found; my $lines_skipped; while (scalar(@content)) { my $line = shift(@content); unless ($line =~ m/(userlinks|vandal)\|\s*$re_user\s*\}\}/i) { push(@new_content,$line); next if ($line =~ m/(userlinks|vandal)\|username/i); if($line =~ m/\{\{IPvandal\|/i) { $ips_left++; } elsif($line =~ m/\{\{(userlinks|vandal)\|/i) { $users_left++; } } else { $found = 1; while ((scalar(@content)) && !($content[0] =~ m/\{\{(userlinks|I?P?vandal)\|/i)) { my $removed = shift(@content); $lines_skipped++ if (length($removed) > 0); } } } $page->{'content'} = join("\n",@new_content); return unless($found); return unless($page->{'content'}); my $length = ((defined($duration)) ? (' '.$duration) : ('')); $length = ' indef ' if ($duration eq 'indef'); my $tally = (($ips_left || $users_left) ? ($ips_left.' IP(s) & '.$users_left.' User(s) left.') : ('List empty.')); my $skipped = (($lines_skipped) ? (" $lines_skipped comment(s) removed.\n") : ('')); $page->{'summary'} = 'rm [[Special:Contributions/'.$user.'|'.$user.']] (blocked'.$length.'by [[User:'.$blocker.'|'.$blocker.']] '.$block_type.'). '.$skipped.$tally; $page->save(); warn "rm '$user': $page_name\n"; sleep($write_rate); } sub timeconv { my($seconds) = $_[0]; return (undef) unless ($seconds); my($result , $used); my($weeks) = int($seconds/604800); $used += ($weeks*604800); my($days) = int(($seconds - $used)/86400); $used += ($days*86400); my($hours) = int(($seconds - $used)/3600); $used += ($hours*3600); my($minutes) = int(($seconds - $used)/60); $result .= $weeks. ' week(s) ' if ($weeks); $result .= $days. ' day(s) ' if ($days); $result .= $hours. ' hour(s) ' if ($hours); $result .= $minutes.' minute(s) ' if ($minutes); die ("Something went wrong with the duration calculation, got negative number: $seconds\n") if (($seconds < 0) || ($weeks < 0) || ($days < 0) || ($hours < 0) || ($minutes < 0)); return($result); }