User:Beetstra/unblockbot2
Code of unblockbot. You need everything between the <pre> and </pre> tags below.
- Bot is written in perl
- Uses perlwikipedia -> see [1]
- You need to create a file with the password for the bot on IRC. The name of the file has to be 'unblockbot-password' and can only contain the password.
# UnBlockBot - a Block reporting bot for mediawiki projects. # Written by Dirk Beetstra, 2007. # You need perlwikipedia.pm -> http://code.google.com/p/perlwikipedia/ #Passwords are stored in a separate file, 'unblockbot-password', create this file in the same directory as this file, # with only the password in it (no CR or any other thing). #First, let's declare our modules. use strict; #use warnings; use POE; use POE::Component::IRC::State; use POE::Component::IRC::Plugin::BotAddressed; use POE::Component::IRC::Plugin::Connector; use perlwikipedia; my %settings : shared; $settings{checkevery} = 600; # number of reported cases in this run $settings{blocklist} = [()]; $settings{counter} = 50; $settings{interval} = 50; $settings{boottime} = time(); $settings{message} = time(); $settings{rcmessage} = time(); $settings{oldcounter} = 0; #Now we'll set up the mechanism we'll use for editing/retrieving pages my $editor=Perlwikipedia->new; #Declare all sorts of IRC-related goodness my $nickname = 'UnBlockBot2'; # Bots nickname my $username = 'UnBlockBot2'; # Bots username open(PASS,'unblockbot-password'); # A file with only the password, no carriage return sysread(PASS, my $password, -s(PASS)); # No password in sourcecode. close(PASS); $password=~s/\n//; # IRC password my $ircname = 'UnblockBot - block reports (by [[en:User:Beetstra]])'; # IRC name my @channels = ( # Listening to channels '#wikipedia-en-unblock', ); my @rcchannels = ( '#en.wikipedia', ); my $connections = { # http://freenode.net/irc_servers.shtml 'niven.freenode.net' => { port => 8001, channels => [ @channels ], }, 'irc.wikimedia.org' => { port => 6667, channels => [ @rcchannels ], }, }; # We create a new PoCo-IRC objects and components. foreach my $server ( keys %{ $connections } ) { POE::Component::IRC->spawn( alias => $server, nick => $nickname, ircname => $ircname, ); } POE::Session->create( inline_states => { _start => \&_start, irc_registered => \&irc_registered, irc_001 => \&irc_001, irc_public => \&irc_public, irc_bot_addressed => \&irc_bot_addressed, }, heap => { config => $connections }, ); $poe_kernel->run(); exit 0; sub _start { my ($kernel,$session) = @_[KERNEL,SESSION]; # Send a POCOIRC_REGISTER signal to all poco-ircs $kernel->signal( $kernel, 'POCOIRC_REGISTER', $session->ID(), 'all' ); undef $kernel; undef $session; } # We'll get one of these from each PoCo-IRC that we spawned above. sub irc_registered { my ($kernel,$heap,$sender,$irc_object) = @_[KERNEL,HEAP,SENDER,ARG0]; my $alias = $irc_object->session_alias(); my %conn_hash = ( server => $alias, port => $heap->{config}->{ $alias }->{port}, ); # In any irc_* events SENDER will be the PoCo-IRC session $kernel->post( $sender, 'connect', \%conn_hash ); $irc_object->plugin_add( 'BotAddressed', POE::Component::IRC::Plugin::BotAddressed->new(eat=>1) ); $heap->{connector} = POE::Component::IRC::Plugin::Connector->new( delay => 120 ); $irc_object->plugin_add( 'Connector' => $heap->{connector} ); undef $kernel; undef $heap; undef $sender; undef $irc_object; undef $alias; } sub irc_001 { my ($kernel,$heap,$sender) = @_[KERNEL,HEAP,SENDER]; # Get the component's object at any time by accessing the heap of # the SENDER my $poco_object = $sender->get_heap(); print "Connected to ", $poco_object->server_name(), "\n"; my $alias = $poco_object->session_alias(); my @channels = @{ $heap->{config}->{ $alias }->{channels} }; if ( $poco_object->server_name eq 'niven.freenode.net') { $kernel->post($sender=>privmsg=>"NickServ","identify $password"); sleep 5; $kernel->post( $sender => join => $_ ) for @channels; } else { $kernel->post( $sender => join => $_ ) for @channels; } $heap->{seen_traffic} = 1; $kernel->delay( autoping => 300 ); undef $kernel; undef $heap; undef $sender; undef $poco_object; undef $alias; undef @channels; undef; } sub irc_public { my ($kernel,$heap,$sender,$who,$where,$message) = @_[KERNEL,HEAP,SENDER,ARG0,ARG1,ARG2]; my $nick = (split /!/,$who)[0]; my ($cloak)=( split /@/, $who)[1]; my $channel = $where->[0]; my $jchannel; if (lc($message) eq '!unblock') { foreach $jchannel(@rcchannels) { $kernel->post( 'irc.wikimedia.org' => join => $jchannel ); } foreach $jchannel(@channels) { $kernel->post( 'niven.freenode.net' => join => $jchannel ); } readandreport($channel, $kernel, $nick, 0, 0); $settings{counter} = 0; } if (lc($message) eq '!new') { $kernel->post( 'niven.freenode.net' => privmsg => '#wikipedia-en-unblock' => "Hi $nick. Parsing unblock requests ..." ); readandreport($channel, $kernel, $nick, 1, 0); $settings{counter} = 0; } if (($nick == 'rc') && ($message =~ m/User talk:/)) { $settings{counter}++; if ($message =~ m/block/i) { $settings{counter} = 0; readandreport($channel, $kernel, $nick, 1, 1); } } if ($settings{counter} > $settings{interval}) { foreach $jchannel(@rcchannels) { $kernel->post( 'irc.wikimedia.org' => join => $jchannel ); } foreach $jchannel(@channels) { $kernel->post( 'niven.freenode.net' => join => $jchannel ); } $settings{counter} = 0; readandreport($channel, $kernel, $nick, 1, 1); } if ($channel = "#en.wikipedia") {$settings{rcmessage} = time(); } if ($channel = "#wikipedia-en-unblock") {$settings{message} = time(); } } sub irc_bot_addressed { # Bot commands my ($kernel,$heap,$sender,$who,$where,$message) = @_[KERNEL,HEAP,SENDER,ARG0,ARG1,ARG2]; my $nick = (split /!/,$who)[0]; my ($cloak)=( split /@/, $who)[1]; my $channel = $where->[0]; $message =~ s/\cC\d{1,2}(?:,\d{1,2})?|[\cC\cB\cI\cU\cR\cO]//g; #Kill any color codes. my $minute; my $second; my $hour; my $dayOfYear; my $theTime; my $uptime; my $timedifference; my $message_to_send; if ((lc($message) eq 'unblock') || (lc($message) eq "")) { readandreport($channel, $kernel, $nick, 0, 0); } if (lc($message) eq 'new') { readandreport($channel, $kernel, $nick, 1, 0); } if (lc($message) eq 'quit' || lc($message) eq 'die') { if (lc($cloak) eq "wikimedia/beetstra" || lc($cloak) eq "wikimedia/versageek") { $kernel->signal($kernel, 'POCOIRC_SHUTDOWN', "Und sterb' ich denn, so sterb' ich doch ... Durch sie, durch sie, ..."); die "Asked to quit by $nick.\n"; } else { $kernel->post( 'niven.freenode.net' => privmsg => '#wikipedia-en-unblock' => "Only Beetstra and Versageek can tell me to quit." ); } } if ($message=~ m/^status/i ) { # ask for status $timedifference = time() - $settings{boottime}; $minute = int($timedifference / 60); $second = $timedifference - $minute * 60; $hour = int($minute / 60); $minute = $minute - $hour * 60; $dayOfYear = int($hour / 24); $hour = $hour - $dayOfYear * 24; if (length("$hour") == 1) { $hour = "0$hour"; } if (length("$minute") == 1) { $minute = "0$minute"; } if (length("$second") == 1) { $second = "0$second"; } if ($dayOfYear > 1) { $theTime = "$dayOfYear days, $hour:$minute:$second hours"; } elsif ($dayOfYear == 1) { $theTime = "$dayOfYear day, $hour:$minute:$second hours"; } else { if ($hour > 1) { $theTime = "$hour hours $minute:$second minutes"; } elsif ($hour == 1) { $theTime = "$hour hour $minute:$second minutes"; } else { if ($minute > 1) { $theTime = "$minute minutes $second seconds"; } elsif ($minute == 1) { $theTime = "$minute minute $second seconds"; } else { $theTime = "$second seconds"; } } } $uptime = $timedifference/60; $message_to_send="$nick:"; $message_to_send.=" Uptime: $theTime."; $timedifference = time() - $settings{rcmessage}; $minute = int($timedifference / 60); $second = $timedifference - $minute * 60; $hour = int($minute / 60); $minute = $minute - $hour * 60; $dayOfYear = int($hour / 24); $hour = $hour - $dayOfYear * 24; if (length("$hour") == 1) { $hour = "0$hour"; } if (length("$minute") == 1) { $minute = "0$minute"; } if (length("$second") == 1) { $second = "0$second"; } if ($dayOfYear > 1) { $theTime = "$dayOfYear days, $hour:$minute:$second hours"; } elsif ($dayOfYear == 1) { $theTime = "$dayOfYear day, $hour:$minute:$second hours"; } else { if ($hour > 1) { $theTime = "$hour hours $minute:$second minutes"; } elsif ($hour == 1) { $theTime = "$hour hour $minute:$second minutes"; } else { if ($minute > 1) { $theTime = "$minute minutes $second seconds"; } elsif ($minute == 1) { $theTime = "$minute minute $second seconds"; } else { $theTime = "$second seconds"; } } } $message_to_send.=" Last RC $theTime ago."; $kernel->post( $sender => privmsg => '#wikipedia-en-unblock' => $message_to_send ); } } sub readandreport { my $channel = shift; my $kernel = shift; my $nick = shift; my $onlyknown = shift; my $auto = shift; if ($auto) { $onlyknown = 1; } my $known; my @blockedusers = (); my $difference; my $blockedusers; my @autoblockedusers = (); my $autoblockedusers; my @usernameblockedusers = (); my $usernameblockedusers; my $difflist; my $add; my $userlist; my $new; my $counter; my @blocks = (); my $blocks; my $page = $editor->{mech}->get("http://en.wikipedia.org/w/index.php?title=Category:Requests_for_unblock&action=render")->decoded_content; @blockedusers = $page=~m/>User talk:(.*?)</sg; $page = $editor->{mech}->get("http://en.wikipedia.org/w/index.php?title=Category:Requests_for_unblock-auto&action=render")->decoded_content; @autoblockedusers = $page=~m/>User talk:(.*?)</sg; $page = $editor->{mech}->get("http://en.wikipedia.org/w/index.php?title=Category:Requests_for_username_changes_when_blocked&action=render")->decoded_content; @usernameblockedusers = $page=~m/>User talk:(.*?)</sg; print("\n"); print("new command - $onlyknown - $auto - $settings{counter}\n"); print( @blockedusers . "\n"); my @blocklist = @{$settings{blocklist}}; delete $settings{blocklist}; print( @blocklist . "\n"); print("end of listing\n"); if (@blockedusers) { $userlist = ""; $counter = 0; my $by; my $at; my $for; $new = 0; foreach $blockedusers(@blockedusers) { $counter++; @blocks = (); $userlist = "\x034[[User talk:$blockedusers]]\x03"; $add = ""; $page = $editor->{mech}->get("http://en.wikipedia.org/w/index.php?title=Special:Log&type=block&page=User:$blockedusers")->decoded_content; @blocks = $page =~ m/(<li>.*?blocked.*?<\/li>)/; $known = 0; if (@blocklist) { $known = 0; foreach $blocks(@blocklist) { print(" Compare [$blocks] -> [$blockedusers]"); if ($blocks eq $blockedusers) { $known = 1; print(" - Known"); } print("\n"); } unless ($known) { $userlist .= " \x034NEW\x03"; $new++; } } else { $userlist .= " \x034NEW\x03"; $new++; } print (" -> $onlyknown - $known \n"); if ($onlyknown == 1) { if ($known == 0) { print("Unknown found\n"); if ((@blocks) && (@blocks[0] =~ m/User talk:$blockedusers/)) { $blocks = @blocks[0]; if ($blocks =~ m/Special:Contributions\/(.*?)\"/) { $by = $1; if ($blocks =~ m/<li>(.*?) <a/) { $at = $1; $userlist .= " - Blocked at $at"; } if ($blocks =~ m/\<span class="comment"\>\((.*?)\)\<\/span\>/) { my $reason = $1; $reason =~ s/\<[^\>]*?\>//g; $userlist .= " - Reason: '$reason'"; } $userlist .= ", by [[:en:user:$by]]"; if ($blocks =~ m/<span title=(.*?)>(.*?)<\/span>/) { $for = $2; $userlist .= ", for $for"; } } } else { $userlist .= " - no blocking admin found"; } if (@autoblockedusers) { foreach $autoblockedusers(@autoblockedusers) { if ($autoblockedusers eq $blockedusers) { $userlist .= " - Autoblock removal request"; } } } if (@usernameblockedusers) { foreach $usernameblockedusers(@usernameblockedusers) { if ($usernameblockedusers eq $blockedusers) { $userlist .= " - Username change request"; } } } $kernel->post( 'niven.freenode.net' => privmsg => '#wikipedia-en-unblock' => "$new - $userlist" ); } } else { if ((@blocks) && (@blocks[0] =~ m/User talk:$blockedusers/)) { $blocks = @blocks[0]; if ($blocks =~ m/Special:Contributions\/(.*?)\"/) { $by = $1; if ($blocks =~ m/<li>(.*?) <a/) { $at = $1; $userlist .= " - Blocked at $at"; } if ($blocks =~ m/\<span class="comment"\>\((.*?)\)\<\/span\>/) { my $reason = $1; $reason =~ s/\<[^\>]*?\>//g; $userlist .= " - Reason: '$reason'"; } $userlist .= ", by [[:en:user:$by]]"; if ($blocks =~ m/<span title=(.*?)>(.*?)<\/span>/) { $for = $2; $userlist .= ", for $for"; } } } else { $userlist .= " - no blocking admin found"; } if (@autoblockedusers) { foreach $autoblockedusers(@autoblockedusers) { if ($autoblockedusers eq $blockedusers) { $userlist .= " - Autoblock"; } } } if (@usernameblockedusers) { foreach $usernameblockedusers(@usernameblockedusers) { if ($autoblockedusers eq $blockedusers) { $userlist .= " - Username change request"; } } } $kernel->post( 'niven.freenode.net' => privmsg => '#wikipedia-en-unblock' => "$counter - $userlist" ); } print ("$counter - $userlist\n"); } $difference = $counter - $settings{oldcounter}; if ($difference < 0 ) { $difflist = ""; foreach $blocks(@blocklist) { $known = 0; foreach $blockedusers(@blockedusers) { print ("$blocks -> $blockedusers"); if ($blocks eq $blockedusers) { $known = 1; print (" - Still there"); } print("\n"); } if ($known == 0) { $difflist .= "[[User talk:$blocks]] "; } } $kernel->post( 'niven.freenode.net' => privmsg => '#wikipedia-en-unblock' => "Handled: $difflist" ); } if ($auto) { unless (@blocklist eq @blockedusers) { if ($counter == 1) { $kernel->post( 'niven.freenode.net' => privmsg => '#wikipedia-en-unblock' => "Autoreport: there is one user in [[Category:Requests for unblock]] ($new new)." ); } else { $kernel->post( 'niven.freenode.net' => privmsg => '#wikipedia-en-unblock' => "Autoreport: there are $counter users in [[Category:Requests for unblock]] ($new new)." ); } } } else { if ($counter == 1) { $kernel->post( 'niven.freenode.net' => privmsg => '#wikipedia-en-unblock' => "There is one user in [[Category:Requests for unblock]] ($new new)." ); } else { $kernel->post( 'niven.freenode.net' => privmsg => '#wikipedia-en-unblock' => "There are $counter users in [[Category:Requests for unblock]] ($new new)." ); } } } else { if (@blocklist) { $difflist = ""; foreach $blocks(@blocklist) { $difflist .= "[[User talk:$blocks]] "; } $kernel->post( 'niven.freenode.net' => privmsg => '#wikipedia-en-unblock' => "Handled: $difflist" ); } if ($auto) { unless (@blocklist == @blockedusers) { $kernel->post( 'niven.freenode.net' => privmsg => '#wikipedia-en-unblock' => "Autoreport: there are currently no users in [[Category:Requests for unblock]]" ); } } else { $kernel->post( 'niven.freenode.net' => privmsg => '#wikipedia-en-unblock' => "There are currently no users in [[Category:Requests for unblock]]" ); } } $settings{blocklist} = [@blockedusers]; $settings{oldcounter} = $counter; undef $channel; undef $kernel; undef $nick; undef $onlyknown; undef $auto; undef $known; undef @blockedusers; undef $difference; undef $blockedusers; undef @autoblockedusers; undef $autoblockedusers; undef @usernameblockedusers; undef $usernameblockedusers; undef $difflist; undef $add; undef $userlist; undef $new; undef $counter; undef @blocks; undef $blocks; undef $page; undef @blocklist; }