User:XLinkBot/Code/XLinkBot.pl
From Wikipedia, the free encyclopedia
< User:XLinkBot | Code
#First, let's declare our modules. use POE qw(Component::IRC Component::IRC::Plugin::BotAddressed); use perlwikipedia; use DBI; use HTML::Entities; use LWP::UserAgent; use Date::Parse qw(str2time); #Now we'll set up the mechanism we'll use for editing/retrieving pages my $username = "XLinkBot"; my $editor=Perlwikipedia->new($username,$username); my $diffFetcher=LWP::UserAgent->new; $diffFetcher->agent("LinkParser/2.0"); my %info; my $number_of_jobs=0; $info{timeon}=localtime(); $info{users}=0; $info{average_time}=0; my @revert_times; open(PASS,'xlinkbot-mysql-password'); sysread(PASS, my $mysql_password, -s(PASS)); close(PASS); $mysql_password=~s/\n//; open(PASS,'xlinkbot-wiki-password'); sysread(PASS, my $wikipedia_password, -s(PASS)); close(PASS); $wikipedia_password=~s/\n//; open(PASS,'xlinkbot-nickserv-password'); sysread(PASS, my $nickserv_password, -s(PASS)); close(PASS); $nickserv_password=~s/\n//; $editor->login($username,$wikipedia_password); my $login_test_page=$editor->_get("Main_Page"); if ($login_test_page->decoded_content=~m/var wgUserName = "$username"/) { print "Logged into Wikipedia.\n"; } else { die "Not logged into Wikipedia.\n"; } my $mysql_handle=DBI->connect("dbi:mysql:squelchbot;localhost","squelchbot",$mysql_password); $mysql_handle->{mysql_auto_reconnect}=1; #Declare all sorts of IRC-related goodness my $nickname = 'XLinkBot'; my $ircname = 'anti-spam bot (Beetstra, Versageek)'; my $ircserver = 'clarke.freenode.net'; my $port = 8001; my @channels = ( '#wikipedia-en-spam', '#beetstra-spam-bot-channel', '#cvn-sw-spam', '#wikipedia-spam-t' ); #Set up various data structures my %page_locks; my %user_locks; my %settings; my $settingspage=$editor->get_text("User:XLinkBot/Settings"); my @settinglist = split(/\n/,$settingspage); $settings{'AntiVandalismBots'} = "VoABot II|ClueBot"; $settings{'RevertList'} = "User:SquelchBot/RevertList"; $settings{'OverrideList'} = "User:SquelchBot/OverrideList"; $settings{'BlackListSource'} = "Wiki"; $settings{'reverting_on'} = 1; $settings{'revert_once'} = 1; $settings{'detect_refs'} = 1; $settings{'size_limit'} = 1500; $settings{'autoconfirm_limit'} = 604800; $settings{'3RR_Reverttime'} = 108000; $settings{'3RR_Reverts'} = 2; foreach my $setting (@settinglist) { unless ($setting =~ m/#/) { if( $setting =~ m/(.+?)=(.+)/) { $settings{$1}=$2; print ("Setting $1 to $2\n"); } } } my $irc=POE::Component::IRC->spawn; $irc->plugin_add( 'BotAddressed', POE::Component::IRC::Plugin::BotAddressed->new(eat=>1) ); POE::Session->create( inline_states => { _start => \&bot_start, irc_001 => \&on_connect, irc_public => \&on_public, irc_bot_addressed => \&irc_bot_addressed, irc_msg => \&irc_msg, }, ); $poe_kernel->run(); exit 0; sub bot_start { my $kernel = $_[KERNEL]; my $heap = $_[HEAP]; my $session = $_[SESSION]; $irc->yield( register => "all" ); $irc->yield( connect => { Nick => $nickname, Username => $username, Ircname => $ircname, Server => $ircserver, Port => $port, } ); } sub on_connect { print "Connected to $ircserver.\n"; $irc->yield(privmsg=>"NickServ","identify $nickserv_password"); sleep 5; foreach $channel (@channels) { $irc->yield(join=>$channel); } } sub on_public { my ($who,$where,$message) = @_[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 $lcmessage = lc($message); if ( $channel eq '#beetstra-spam-bot-channel' ) { #Are we talking in the bot channel? if (check_mysql("authorized_bots",$nick)) { #Yep, it's a bot $number_of_jobs++; processalert($message); #Process the message. --$number_of_jobs; return; } #It's a bot } #It's a bot channel if ( $lcmessage =~ m/^aspf-en link bl add (.+)/ || $message =~ m/^enlinkwatcher2 link bl add (.+)/ || $message =~ m/^intlinkwatcher2 link bl add (.+)/ || $message =~ m/^delinkwatcher2 link bl add (.+)/ || $message =~ m/^bigwikilw2 link bl add (.+)/ | $lcmessage =~ m/^aspf-en: link bl add (.+)/ || $message =~ m/^enlinkwatcher2: link bl add (.+)/ || $message =~ m/^intlinkwatcher2: link bl add (.+)/ || $message =~ m/^delinkwatcher2: link bl add (.+)/ || $message =~ m/^bigwikilw2: link bl add (.+)/ || $message =~ m/^link! bl add (.+)/) { #adding to linkwatcher revertlist? my ($toadd,$reason) = split(/ /,$1,2); insert_mysql("quarantine",$toadd);#Initialize the key with a blank def. $irc->yield(privmsg=>$channel,"Item \"$toadd\" has been added to my quarantine list." ); #Report back } #adding to lw revertlist if ( $lcmessage =~ m/^aspf-en link bl del (.+)/ || $message =~ m/^enlinkwatcher2 link bl del (.+)/ || $message =~ m/^intlinkwatcher2 link bl del (.+)/ || $message =~ m/^delinkwatcher2 link bl del (.+)/ || $message =~ m/^bigwikilw2 link bl del (.+)/ | $lcmessage =~ m/^aspf-en: link bl del (.+)/ || $message =~ m/^enlinkwatcher2: link bl del (.+)/ || $message =~ m/^intlinkwatcher2: link bl del (.+)/ || $message =~ m/^delinkwatcher2: link bl del (.+)/ || $message =~ m/^bigwikilw2: link bl del (.+)/ || $message =~ m/^link! bl del (.+)/) { #deling to linkwatcher revertlist? my ($toadd,$reason) = split(/ /,$1,2); my $todel = $1; my $sql="DELETE FROM quarantine WHERE rule=" . $mysql_handle->quote($todel); query_mysql($sql); $irc->yield(privmsg=>$channel,"Item \"$todel\" has been removed from my quarantine list." ); }#deleting from lw revertlist } sub irc_bot_addressed { my ($who,$where,$message) = @_[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 if ( $channel eq '#wikipedia-en-spam' | $channel eq '#wikipedia-spam-t') { #Command channel? my $verified=0; $verified=check_mysql("trusted_users",$cloak); if ($message=~m/^lock page (.+?) (.+)/) { my $rule=$1; my $article=$2; if ($verified) { $page_locks{$rule}=$article; $irc->yield(privmsg=>$channel,"Rule $rule now locked to [[:en:$article]]."); } else { $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); } } if ($message=~m/^lock user (.+?) (.+)/) { my $rule=$1; my $touser=$2; if ($verified) { $page_locks{$rule}=$touser; $irc->yield(privmsg=>$channel,"Rule $rule now locked to [[:en:User:$touser]]."); } else { $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); } } if ($message=~m/^unlock (.+)/) { my $rule=$1; if ($verified) { delete $page_locks{$rule}; $irc->yield(privmsg=>$channel,"Rule $rule unlocked."); } else { $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); } } if ($message=~m/^autoconfirm (\d+)/) { my $age=$1; if ($verified) { $age*=24 * 60 * 60; $settings{'autoconfirm_limit'}=$age; $irc->yield(privmsg=>$channel,"Autoconfirm limit set to $settings{'autoconfirm_limit'}."); } else { $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); } } if ($message=~m/^add watch (.+)/) { my $rule=$1; if ($verified) { insert_mysql("watched_rules",$rule); $irc->yield(privmsg=>$channel,"Now watching for $rule"); } else { $irc->yield(privmsg=>$channel,"$nick is not in my list of trusted users."); } } if ($message=~m/^remove watch (.+)/) { my $rule=$1; if ($verified) { my $sql="DELETE FROM watched_rules WHERE rule=" . $mysql_handle->quote($rule); query_mysql($sql); $irc->yield(privmsg=>$channel,"Stopped watching for $rule"); } else { $irc->yield(privmsg=>$channel,"$nick is not in my list of trusted users"); } } if ($message=~m/^activate override (.+)/) { my $rule=$1; if ($verified) { set_override($rule,1); $irc->yield(privmsg=>$channel,"$rule override turned on."); } else { $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); } } if ($message=~m/^deactivate override (.+)/) { my $rule=$1; if ($verified) { set_override($rule,0); $irc->yield(privmsg=>$channel,"$rule override turned off."); } else { $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); } } if ($message=~m/^activate hard override (.+)/) { my $rule = $1; if ($verified) { my $temp = $mysql_handle->quote($rule); query_mysql("INSERT INTO hard_overrides (rule) VALUES ($temp)"); $irc->yield(privmsg=>$channel,"$rule hard override turned on"); } else { $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); } } if ($message=~m/^deactivate hard override (.+)/) { my $rule = $1; if ($verified) { my $temp = $mysql_handle->quote($rule); query_mysql("DELETE FROM hard_overrides WHERE rule=$temp"); $irc->yield(privmsg=>$channel,"$rule hard override turned off"); } else { $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); } } if ($message=~m/^status/) { my $message_to_send="I've been active since $info{timeon}. I've reverted $info{users} times. "; if ($settings{'revert_once'}) { $message_to_send.="I'm currently in calm mode. "; } else { $message_to_send.="I'm currently in angry mode. "; } $message_to_send.="Autoconfirm limit is $settings{'autoconfirm_limit'} seconds."; my $average_time; foreach $time (@revert_times) { $average_time+=$time; } if (scalar @revert_times) { $info{average_time}=$average_time / (scalar @revert_times); } $message_to_send.=" Average reversion time is " . $info{average_time} . " seconds."; $irc->yield(privmsg=>$channel,$message_to_send); } if ($message=~m/^mode (.+)/) { my $mode=$1; if ($verified) { if ($mode=~/angry/) { $settings{'revert_once'}=0; $irc->yield(privmsg=>$channel,"Safety check disabled."); } elsif($mode=~/calm/) { $settings{'revert_once'}=1; $irc->yield(privmsg=>$channel,"Safety check enabled."); } else { $irc->yield(privmsg=>$channel,"Mode $mode not recognized."); } } else { $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); } } if ($message=~m/^size (\d+)/) { #It's a size command my $newsize=$1; if ($verified) { #Are they supposed to do this? $settings{'size_limit'}=$newsize; #Change the size $irc->yield(privmsg=>$channel,"Size limit changed to $settings{'size_limit'}."); #Report back } #They're supposed to do this else { #They're not supposed to do this $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); #Tell them they've been naughty } #They're not supposed to do this } if ( $message =~ m/^references/ ) { #Checking refs? if ($verified) { #Authed? $settings{'detect_refs'}=1; $irc->yield(privmsg=>$channel,"Now detecting references."); }#Authed else { #Not authed? $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); }#Not authed }#References command if ( $message =~ m/^noreferences/ ) { #Checking refs? if ($verified) { #Authed? $settings{'detect_refs'}=0; $irc->yield(privmsg=>$channel,"References detection disabled."); }#Authed else { #Not authed? $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); }#Not authed }#NoReferences command if ($message=~m/^add authorized (.+)/) { #Adding a bot my $botname=$1; if ($verified) { $exists=check_mysql("authorized_bots",$botname); unless ($exists) { #Make sure it doesn't exist insert_mysql("authorized_bots",$botname); $irc->yield(privmsg=>$channel,"New authorized bot \"$botname\" added."); return; } if ($exists) { $irc->yield(privmsg=>$channel,"Bot already exists in my database."); return; } } else { $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); } } if ($message=~m/^remove authorized (.+)/) { my $botname=$1; if ($verified) { $exists=check_mysql("authorized_bots",$botname); unless ($exists) { $irc->yield(privmsg=>$channel,"Bot does not exist in my database."); return; } if ($exists) { my $sql="DELETE FROM authorized_bots WHERE bot_name=" . $mysql_handle->quote($botname); query_mysql($sql); $irc->yield(privmsg=>$channel,"Authorized bot \"$botname\" deleted."); return; } } else { $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); } } if ($message=~m/^depth (.+)/) { #It's a depth command my $newdepth=$1; if ($verified) { #Are they supposed to do this? $searchdepth=$newdepth; #Change the depth $irc->yield(privmsg=>$channel,"Search depth changed to $searchdepth."); #Report back } #They're supposed to do this else { #They're not supposed to do this $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); #Tell them they've been naughty } #They're not supposed to do this } #It's a depth command if ( $message =~ m/^revert on/ ) { #Are we going to go into revert mode? if ($verified) { #Verified? $irc->yield(privmsg=>$channel,"Reverting enabled."); $settings{'reverting_on'}=1; #Activate reverting } #Verified? else { #Not verified. $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); } #Not verified } #Revert command if ( $message =~ m/^norevert/ || $message =~ m/^revert off/ ) { #Turning off reversion? if ($verified) { #Authed? $settings{'reverting_on'}=0; $irc->yield(privmsg=>$channel,"Reverting disabled."); }#Authed else { #Not authed? $irc->yield(privmsg=>$channel,"User $nick not in my list of trusted users."); }#Not authed }#Norevert command if ( $message =~ m/^blacklist search (.+)/ || $message =~ m/^revertlist search (.+)/ ) { #Search the revertlist my $search = $1; my $exists=check_mysql("blacklist",$search); unless($exists) { #Darn, didn't find it $irc->yield(privmsg=>$channel,"$search was not found in my revertlist." ); } #Didn't find string if ($exists) { #Hoorah, we found it $irc->yield(privmsg=>$channel,"$search was found in my revertlist." ); } #Found string } #Searching revertlist if ( $message =~ m/^approve (.+)/ ) { my ($toapprove,$reason) = split(/ /,$1,2); if ($verified) { my $exists=check_mysql("quarantine",$toapprove); unless ($exists) { $irc->yield(privmsg=>$channel,"Item $toapprove does not exist in my quarantine list." ); } if ($exists) { insert_mysql("blacklist",'DEFAULT',$toapprove,'NULL',$cloak,$reason); my $sql="DELETE FROM quarantine WHERE rule=" . $mysql_handle->quote($toapprove); query_mysql($sql); $irc->yield(privmsg=>$channel,"Item $toapprove has been approved and added to my revertlist ('$reason')." ); logit("$nick added revertlist rule $toapprove"); } } elsif (!$verified) { $irc->yield(privmsg=>$channel,"User $nick is not in my list of trusted users." ); } } if ( $message =~ m/^deny (.+)/ ) { my $todeny = $1; if ($verified) { my $exists=check_mysql("quarantine",$todeny); unless ($exists) { $irc->yield(privmsg=>$channel,"Item $todeny does not exist in my quarantine list."); } if ($exists) { my $sql="DELETE FROM quarantine WHERE rule=" . $mysql_handle->quote($todeny); query_mysql($sql); $irc->yield(privmsg=>$channel,"Item $todeny has been denied and has been removed from my quarantine list."); } } else { $irc->yield(privmsg=>$channel,"User $nick is not in my list of trusted users." ); } } if ( $message =~ m/^blacklist add (.+?) (.+)/ ) { my ($toapprove,$reason) = split(/ /,$1,2); if ($verified) { my $exists=check_mysql("quarantine",$toapprove); unless ($exists) { $irc->yield(privmsg=>$channel,"Item $toapprove does not exist in my quarantine list." ); } if ($exists) { if ($reason eq "") { $irc->yield(privmsg=>$channel,"You have not provided a reason for rule '$toapprove'."); } else { insert_mysql("blacklist",'DEFAULT',$toapprove,'NULL',$cloak,$reason); my $sql="DELETE FROM quarantine WHERE rule=" . $mysql_handle->quote($toapprove); query_mysql($sql); $irc->yield(privmsg=>$channel,"Item $toapprove has been approved and added to my revertlist ('$reason')." ); logit("$nick added revertlist rule $toapprove"); } } } elsif (!$verified) { $irc->yield(privmsg=>$channel,"User $nick is not in my list of trusted users." ); } } if ( $message =~ m/^blacklist remove (.+)/ ) { my $toremove = $1; if ($verified) { my $exists=check_mysql("blacklist",$toremove); unless ($exists) { $irc->yield(privmsg=>$channel,"Item $toremove does not exist in my revertlist." ); } if ($exists) { my $sql="DELETE FROM blacklist WHERE rule=" . $mysql_handle->quote($toremove); query_mysql($sql); $irc->yield(privmsg=>$channel,"Item $toremove has been removed from my revertlist."); } } else { $irc->yield(privmsg=>$channel,"User $nick is not in my list of trusted users"); } } if ( $message =~ m/^add media (.+)/ ) { my $totrust = $1; if ($verified) { my $exists=check_mysql("media",$totrust); if ($exists) { $irc->yield(privmsg=> $channel => "Media $totrust already in list."); } unless ($exists) { insert_mysql("media",$totrust); $irc->yield(privmsg=> $channel => "Media: '$totrust' added, users adding links matching a rule that includes '$totrust' will now recieve a customised warning."); } } else { $irc->yield(privmsg=> $channel => "User $nick not in my list of trusted users."); } } if ( $message =~ m/^remove media (.+)/ ) { my $todelete = $1; if ($verified) { my $sql="DELETE FROM media WHERE rule=" . $mysql_handle->quote($todelete); query_mysql($sql); $irc->yield(privmsg=> $channel => "Media $todelete has been removed."); } else { $irc->yield(privmsg=> $channel => "User $nick not in my list of trusted users."); } } if ( $message =~ m/^add freehost (.+)/ ) { my $totrust = $1; if ($verified) { my $exists=check_mysql("freehost",$totrust); if ($exists) { $irc->yield(privmsg=> $channel => "Free host $totrust already in list."); } unless ($exists) { insert_mysql("freehost",$totrust); $irc->yield(privmsg=> $channel => "Free host: '$totrust' added, users adding links matching a rule that includes '$totrust' will now recieve a customised warning."); } } else { $irc->yield(privmsg=> $channel => "User $nick not in my list of trusted users."); } } if ( $message =~ m/^remove freehost (.+)/ ) { my $todelete = $1; if ($verified) { my $sql="DELETE FROM freehost WHERE rule=" . $mysql_handle->quote($todelete); query_mysql($sql); $irc->yield(privmsg=> $channel => "Free host $todelete has been removed."); } else { $irc->yield(privmsg=> $channel => "User $nick not in my list of trusted users."); } } if ( $message =~ m/^add petition (.+)/ ) { my $totrust = $1; if ($verified) { my $exists=check_mysql("petition",$totrust); if ($exists) { $irc->yield(privmsg=> $channel => "Petition site $totrust already in list."); } unless ($exists) { insert_mysql("petition",$totrust); $irc->yield(privmsg=> $channel => "Petition site: '$totrust' added, users adding links matching a rule that includes '$totrust' will now recieve a customised warning."); } } else { $irc->yield(privmsg=> $channel => "User $nick not in my list of trusted users."); } } if ( $message =~ m/^remove petition (.+)/ ) { my $todelete = $1; if ($verified) { my $sql="DELETE FROM petition WHERE rule=" . $mysql_handle->quote($todelete); query_mysql($sql); $irc->yield(privmsg=> $channel => "Petition site $todelete has been removed."); } else { $irc->yield(privmsg=> $channel => "User $nick not in my list of trusted users."); } } if ( $message =~ m/^add payperview (.+)/ ) { my $totrust = $1; if ($verified) { my $exists=check_mysql("payperview",$totrust); if ($exists) { $irc->yield(privmsg=> $channel => "Pay per view site $totrust already in list."); } unless ($exists) { insert_mysql("payperview",$totrust); $irc->yield(privmsg=> $channel => "Pay per view: '$totrust' added, users adding links matching a rule that includes '$totrust' will now recieve a customised warning."); } } else { $irc->yield(privmsg=> $channel => "User $nick not in my list of trusted users."); } } if ( $message =~ m/^remove payperview (.+)/ ) { my $todelete = $1; if ($verified) { my $sql="DELETE FROM payperview WHERE rule=" . $mysql_handle->quote($todelete); query_mysql($sql); $irc->yield(privmsg=> $channel => "Pay per view site $todelete has been removed."); } else { $irc->yield(privmsg=> $channel => "User $nick not in my list of trusted users."); } } if ( $message =~ m/^source (.+)/ ) { my $revertfrom = $1; if (lc($cloak) eq "wikimedia/versageek" || lc($cloak) eq "wikimedia/beetstra") { if ($revertfrom =~ m/(SQL|Wiki)/) { $settings{'RevertListSource'} = $revertfrom; $irc->yield(privmsg=> $channel => "Revertlist source is now $revertfrom."); } else { $irc->yield(privmsg=> $channel => "'$revertfrom' is not a valid revertlist source."); } } else { $irc->yield(privmsg=> $channel => "I only trust Versageek and Beetstra to issue this command."); } } if ( $message =~ m/^add trusted (.+)/ ) { my $totrust = $1; if (lc($cloak) eq "wikimedia/versageek" || lc($cloak) eq "wikimedia/beetstra") { my $exists=check_mysql("trusted_users",$totrust); if ($exists) { $irc->yield(privmsg=> $channel => "User cloak $totrust is already in my list of trusted users."); } unless ($exists) { insert_mysql("trusted_users",$totrust); $irc->yield(privmsg=> $channel => "User cloak $totrust has been added to my list of trusted users."); } else { $irc->yield(privmsg=> $channel => "I only trust Versageek and Beetstra to issue this command."); } } if ( $message =~ m/^remove trusted (.+)/ ) { my $todelete = $1; if (lc($cloak) eq "wikimedia/versageek" || lc($cloak) eq "wikimedia/beetstra") { my $sql="DELETE FROM trusted_users WHERE user_cloak=" . $mysql_handle->quote($todelete); query_mysql($sql); $irc->yield(privmsg=> $channel => "User cloak $todelete has been removed from my list of trusted users."); } else { $irc->yield(privmsg=> $channel => "I only trust Versageek and Beetstra to issue this command."); } } if ($message=~m/add exemption (.+?) (.+)/) { my $rule=$1; my $exemption_rule=$2; if ($verified) { update_mysql("blacklist","rule=$rule","exempt=$exemption_rule"); $irc->yield(privmsg=>$channel=>"Changed exemption for $rule to \"$exemption_rule\"."); } else { $irc->yield(privmsg=>$channel=>"User $nick is not in my list of trusted users."); } } if ($message=~m/^remove exemption "(.+?)"/) { my $rule=$1; if ($verified) { update_mysql("blacklist","rule=$rule","exempt="); $irc->yield(privmsg=>$channel=>"Removed exemption for $rule."); } else { $irc->yield(privmsg=>$channel=>"User $nick is not in my list of trusted users."); } } } } } sub parsealert { my $alert = shift; my $pagename; my $user; my $diffurl; my $size; my @rules=(); if ( $alert =~ m/diff=<(.+?)> user=<(.+?)> title=<(.+?)>/ ) { $diffurl =$1; $user =$2; $pagename=$3; } if ($alert=~m/size=<(.+?)>/) { $size=$1; } while ($alert=~m/rule=<(.+?)>/) { my $rule=$1; push(@rules,$rule); $alert=~s/rule=<.+>//; } if ($size=~m/-(\d+)/) { $size=-$1; } elsif ($size=~m/(\d+)/) { $size=$1; } print "Received an alert for $user on $pagename ($diffurl, $size).\n"; return $pagename, $user, $diffurl, $size, @rules; } sub authenticate { my $cloak = shift; my $exists=check_mysql("trusted_users",$cloak); if ($exists) { return 1; } else { return 0; } } sub processalert { my $message=shift; my $start_time=time(); my ( $pagename, $user, $diff, $size, @rules ) = parsealert($message); my $test_page=$editor->{mech}->get("http://en.wikipedia.org/wiki/Main_Page")->decoded_content; my $revisionid=$editor->get_last($pagename,$user); # last edit not by this user # my ( $revisionid ) = $diff =~ m/oldid=(\d+)/; # previous edit print ("Processing [$pagename] - [$user] - [$diff] - [$size].\n"); my $pagecontents=$editor->get_text($pagename) . " "; my $settingspage=$editor->get_text("User:XLinkBot/Settings"); my @settinglist = split(/\n/,$settingspage); foreach my $setting (@settinglist) { unless ($setting =~ m/#/) { if( $setting =~ m/(.+?)=(.+)/) { $settings{$1}=$2; print ("Setting $1 to $2\n"); } } } my $override=0; my $watched=0; my $hard_override=0; my $resolve_blacklisted; my $link; my $rule; my $rules; my @links; my @links2; my $link2; my $links; my $DiffUrl= $diff . "&diffonly=1&action=render"; my $diffContent=$diffFetcher->get($DiffUrl)->content; my @addedPre = (); my @removedPre = (); my @addedlinks = (); my @removedlinks = (); my $addedTotal = ""; my $removedTotal = ""; @addedPre=$diffContent=~m/<td class="diff-addedline"><div>(.*?)<\/div><\/td>/sg; @removedPre=$diffContent=~m/<td class="diff-deletedline"><div>(.*?)<\/div><\/td>/sg; $addedTotal=join(' ', @addedPre) . " "; $removedTotal=join(' ', @removedPre) . " "; $addedTotal =~ s/<span class="diffchange">//g; $addedTotal =~ s/<\/span>//g; $removedTotal =~ s/<span class="diffchange">//g; $removedTotal =~ s/<\/span>//g; decode_entities( $addedTotal ); decode_entities( $removedTotal ); @addedlinks=$addedTotal=~m{(https?://[^\s\]\[\{\}\\\|^~`<>]+)}sgi; @removedlinks=$removedTotal=~m{(https?://[^\s\]\[\{\}\\\|\)\(^~`<>]+)}sgi; my @really_added_links = (); my @really_removed_links = (); my $links_added; my $links_removed; if (@addedlinks) { if (@removedlinks) { foreach $links_added(@addedlinks) { my $found = 0; foreach $links_removed(@removedlinks) { if ($links_removed eq $links_added) { $found = 1; } } unless ($found) { push(@really_added_links,$links_added); } } } else { @really_added_links = @addedlinks; } } $links = join (" ",@really_added_links); $links .= " "; print "[$links]\n"; foreach $rule (@rules) { @links = $links =~ m/(https?[^\s]+$rule[^\s]+)\s/sgi; if (@links) { $link .= "rule: '$rule' (link(s): ". join(" ",@links) . ") "; } else { $link .= "rule: '$rule' "; } } if ($test_page !~m/var wgUserName = "$username"/) { $editor->login($username,$wikipedia_password); if ($test_page !~m/var wgUserName = "$username"/) { $editor->login($username,$wikipedia_password); $settings{'reverting_on'}=0; $irc->yield(privmsg=>"#wikipedia-spam-t"=>"I've become logged-out on Wikipedia, reverting disabled ( $diff ; $rules[0])."); logit("ERROR: I've become logged-out on Wikipedia, reverting disabled ($diff not reverted ) [$link]."); } else { if ($settings{'reverting_on'} == 0) { logit("Login refreshed."); $settings{'reverting_on'}=1; } } } foreach $rule ( @rules ) { if( $rule =~ m/^resolve/ ) { $resolve_blacklisted = 1; $pagecontents .= $rule . " "; } } if ($settings{RevertListSource} eq "SQL") { foreach $rule (@rules) { $override=check_mysql("overrides",$rule); $hard_override=check_mysql("hard_overrides",$rule); } } elsif ($settings{RevertListSource} eq "Wiki") { foreach $rule (@rules) { my $rulespage=$editor->get_text($settings{'OverrideList'}); my @blacklist = split(/\n/,$rulespage); $override = 0; foreach $blacklistrule (@blacklist) { $blacklistrule .= "#"; ($blacklistrule,$garbage) = split(/#/,$blacklistrule); $blacklistrule .= " "; ($blacklistrule,$garbage) = split(/\s/,$blacklistrule); if ($rule eq $blacklistrule) { $override = 1; } } my $rulespage=$editor->get_text($settings{'OverrideList'}); my @blacklist = split(/\n/,$rulespage); $hard_override = 0; foreach $blacklistrule (@blacklist) { $blacklistrule .= "#"; ($blacklistrule,$garbage) = split(/#/,$blacklistrule); $blacklistrule .= " "; ($blacklistrule,$garbage) = split(/\s/,$blacklistrule); if ($rule eq $blacklistrule) { $hard_override = 1; } } } } if ($override) { $irc->yield(privmsg=>"#wikipedia-en-spam","User $user added rule $rule (on override list) on $diff."); $irc->yield(privmsg=>"#wikipedia-spam-t","User $user added rule $rule (on override list) on $diff."); logit("User $user added rule $rule (on override list) on $diff ($link)."); } if ($hard_override) { $irc->yield(privmsg=>"#wikipedia-en-spam","User $user added rule $rule (on hard override list) on $diff."); $irc->yield(privmsg=>"#wikipedia-spam-t","User $user added rule $rule (on hard override list) on $diff."); logit("User $user added rule $rule (on hard override list) on $diff ($link)."); } if ($pagename=~/^($settings{'NoRevertNameSpace'}):/ && $pagename != "User:Beetstra/Sandbox" ) { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Page $pagename is outside of allowed namespace, $diff not reverted ($rules[0])."); $irc->yield(privmsg=>"#wikipedia-spam-t","ERROR: Page $pagename is outside of allowed namespace, $diff not reverted ($rules[0])."); logit("ERROR: Page $pagename is outside of allowed namespace, $diff not reverted; $link."); return; } unless ($user=~m/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/) { my $autoconfirm_user=&autoconfirm($user); print "$user is $autoconfirm_user seconds old, limit is $settings{'autoconfirm_limit'}.\n"; if ($autoconfirm_user>$settings{'autoconfirm_limit'}) { unless ($hard_override) { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Failed to revert to revision $revisionid on $pagename: User $user does not satisfy autoconfirm ( $diff ; $rules[0] )."); logit("ERROR: Failed to revert to $revisionid on $pagename: User $user doesn't meet autoconfirm $settings{'autoconfirm_limit'} ($diff, $link)."); return; } } } if ($size>$settings{'size_limit'}) { unless ($override) { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Failed to revert to $revisionid on $pagename: Edit larger than $settings{'size_limit'} ( $diff ; $rules[0])."); logit("ERROR: Failed to revert to $revisionid on $pagename: Edit larger than $settings{'size_limit'} ($diff; $link)."); return; } } foreach $rule (@rules) { if ($pagecontents=~m/\{\{.+?$rule.+?\}\}/ | $pagecontents=~m/\{\{.+?$rule\}\}/ |$pagecontents=~m/\<ref.+?\>.+?$rule.+?\<\/ref\>/ | $pagecontents=~m/\<ref\>.+?$rule.+?\<\/ref\>/ | $pagecontents=~m/\<!--.+?$rule.+?--\>/ | $pagecontents=~m/\<!--.+?$rule--\>/ | $pagecontents=~m/\<!--$rule.+?--\>/ | $pagecontents=~m/\<!--$rule--\>/) { if ($settings{'detect_refs'}==1) { unless($override) { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Detected \"$rule\" inside of a reference, template or remark, please manually check $diff ."); $irc->yield(privmsg=>"#wikipedia-spam-t","ERROR: Detected \"$rule\" inside of a reference, template or remark, please manually check $diff ."); logit("ERROR: Detected \"$rule\" inside of a reference or template, please manually check ($diff) [$link]."); } return; } } } if ($settings{RevertListSource} eq "SQL") { foreach $rule (@rules) { my $exists=check_mysql("blacklist",$rule); unless ($exists) { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Rule \"$rule\" was not found in my blacklist, so I can't revert on diff $diff ."); logit("ERROR: Rule \"$rule\" was not found in my blacklist, so I can't revert on diff \"$diff\" ($link)."); return; } } } elsif ($settings{RevertListSource} eq "Wiki") { foreach $rule (@rules) { my $rulespage=$editor->get_text($settings{'RevertList'}); my @blacklist = split(/\n/,$rulespage); $exists = 0; foreach $blacklistrule (@blacklist) { $blacklistrule .= "#"; ($blacklistrule,$garbage) = split(/#/,$blacklistrule); $blacklistrule .= " "; ($blacklistrule,$garbage) = split(/\s/,$blacklistrule); if ($rule eq $blacklistrule) { $exists = 1; } } unless ($exists) { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Rule \"$rule\" was not found in my blacklist, so I can't revert on diff $diff ."); logit("ERROR: Rule \"$rule\" was not found in my blacklist, so I can't revert on diff \"$diff\" ($link)."); return; } } } else { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Error in setting for RevertListSource ($settings{RevertListSource} is not valid), see [[:en:User:XLinkBot/Settings]]. , Can't revert on diff $diff "); $irc->yield(privmsg=>"#wikipedia-spam-t","ERROR: Error in setting for RevertListSource ($settings{RevertListSource} is not valid), see [[:en:User:XLinkBot/Settings]]. , Can't revert on diff $diff "); logit("ERROR: Error in setting for RevertListSource ($settings{RevertListSource} is not valid), see [[:en:User:XLinkBot/Settings]]."); return; } foreach $rule (@rules) { unless ($pagecontents=~m/$rule/i) { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Rule \"$rule\" was not found in the on-top version of $pagename ( $diff )."); logit("ERROR: Rule \"$rule\" was not found in the on-top version of $pagename ($diff; $link)."); return; } } if ($settings{RevertListSource} eq "SQL") { foreach $rule (@rules) { if (exists $page_locks{$rule}) { unless ($pagename eq $page_locks{$rule}) { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Rule $rule is locked to page $page_locks{$rule} ( $diff )."); logit("ERROR: Rule $rule is locked to page $page_locks{$rule} ($diff) [$link]."); return; } } } } elsif ($settings{RevertListSource} eq "Wiki") { foreach $rule (@rules) { my $rulespage=$editor->get_text($settings{'PageLocks'}); my @blacklist = split(/\n/,$rulespage); foreach $blacklistrule (@blacklist) { $blacklistrule .= "#"; ($blacklistrule,$garbage) = split(/#/,$blacklistrule); $blacklistrule .= " "; ($blacklistrule,$garbage) = split(/\s/,$blacklistrule); if( $blacklistrule =~ m/(.+?)=(.+)/) { my ($pagelock,$rulelock) = split(/=/,$blacklistrule); unless ($pagename eq $pagelock && $rulelock eq $rule) { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Rule $rule is locked to page $pagelock ( $diff )."); logit("ERROR: Rule $rule is locked to page $pagelock ($diff) [$link]."); return; } } } } } if ($settings{RevertListSource} eq "SQL") { foreach $rule (@rules) { if (exists $user_locks{$rule}) { unless ($pagename eq $user_locks{$rule}) { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Rule $rule is locked to user $user_locks{$rule} ( $diff )."); logit("ERROR: Rule $rule is locked to user $user_locks{$rule} ($diff) [$link]."); return; } } } } elsif ($settings{RevertListSource} eq "Wiki") { foreach $rule (@rules) { my $rulespage=$editor->get_text($settings{'UserLocks'}); my @blacklist = split(/\n/,$rulespage); foreach $blacklistrule (@blacklist) { $blacklistrule .= "#"; ($blacklistrule,$garbage) = split(/#/,$blacklistrule); $blacklistrule .= " "; ($blacklistrule,$garbage) = split(/\s/,$blacklistrule); if( $blacklistrule =~ m/(.+?)=(.+)/) { my ($pagelock,$rulelock) = split(/=/,$blacklistrule); unless ($pagename eq $pagelock && $rulelock eq $rule) { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Rule $rule is locked to user $pagelock ( $diff )."); logit("ERROR: Rule $rule is locked to user $pagelock ($diff) [$link]."); return; } } } } } if (($settings{'reverting_on'}==1) || ($pagename eq "User:Beetstra/Sandbox")) { my $rule=$rules[0]; my $edit_summary="BOT--Reverting edits by [[:en:Special:Contributions/$user|$user]] to revision $revisionid ($rule)"; print "Preparing to revert to $revisionid on \"$pagename\". hard_override=$hard_override,override=$override [$link].\n"; unless ($revisionid==0) { my $safety_status=check_if_safe($pagename,$user,$override,$hard_override,$revisionid,$rule); # if( $safety_status eq 'Reversion' && $override ) { # $safety_status = 'Pass'; # } if( $safety_status eq 'Reversion' && $hard_override ) { $safety_status = 'Pass'; } if ($safety_status eq 'Pass') { my $oldtext=$editor->get_text($pagename,$revisionid); my $revert_response=$editor->edit($pagename,$oldtext,$edit_summary); # my $revert_response=$editor->revert($pagename,$edit_summary,$revisionid)->decoded_content; my $end_time=time(); print ("\n\nRevert response: [($revert_response)]\n\n"); if (($revert_response)=~m/Someone else has changed this page since you started editing it/) { $irc->yield(privmsg=>"#wikipedia-spam-t"=>"Edit-conflicted while reverting to $revisionid on $pagename ( $diff ; $rule)."); logit("ERROR: Edit-conflicted while reverting to $revisionid on $pagename [$diff; $link]."); print "Edit-conflicted on $pagename [$link].\n"; } else { my @history=$editor->get_history($pagename,2); my $reverter = @history[0]->{user}; if ($reverter == $username) { $irc->yield(privmsg=>"#wikipedia-en-spam","Reverted $user to $revisionid on $pagename ( $diff ; $rule)."); print "Reverted to $revisionid on $pagename [$link].\n"; logit("Reverted to $revisionid on $pagename [$link]."); warn_user($user,$diff,$pagename,$link); $info{users}++; update_rules_stats(@rules); push (@revert_times,($end_time-$start_time)); } else { $irc->yield(privmsg=>"#wikipedia-en-spam","User $reverter beat me to reverting $user on $pagename ( $diff ; $rule)."); print "User $reverter beat me to reverting $user on $pagename ( $diff ; $link).\n"; logit("User $reverter beat me to reverting $user on $pagename ( $diff ; $rule)."); } } return; } elsif ($safety_status eq 'Fail') { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Failed to revert to $revisionid on $pagename: Someone has edited since the spammer ( $diff ; $rule)."); logit("ERROR: Failed to revert to $revisionid on $pagename: Someone has edited since the spammer [$link]."); return; } elsif ($safety_status eq 'Alreadydid') { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Failed to revert edits by $user to $revisionid on $pagename: I've already reverted ( $diff ; $rule]."); $irc->yield(privmsg=>"#wikipedia-spam-t","ERROR: Failed to revert edits by $user to $revisionid on $pagename: I've already reverted ( $diff ; $rule]."); logit("ERROR: Failed to revert edits by $user to $revisionid on $pagename: I've already reverted [$link]."); } elsif ($safety_status eq 'AntiVandalismBot') { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Failed to revert edits by $user to $revisionid on $pagename: Previous revert was by another AntiVandalismBot ( $diff ; $rule]."); $irc->yield(privmsg=>"#wikipedia-spam-t","ERROR: Failed to revert edits by $user to $revisionid on $pagename: Previous revert was by another AntiVandalismBot ( $diff ; $rule]."); logit("ERROR: Failed to revert edits by $user to $revisionid on $pagename: Previous revert was by another AntiVandalismBot [$link]."); } elsif ($safety_status eq '3RR') { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Failed to revert edits by $user to $revisionid on $pagename: I already reverted the page 3 times in the last 30 hours, please check ( $diff ; $rule]."); $irc->yield(privmsg=>"#wikipedia-spam-t","ERROR: Failed to revert edits by $user to $revisionid on $pagename: I already reverted the page 3 times in the last 30 hours, please check ( $diff ; $rule]."); logit("ERROR: Failed to revert edits by $user to $revisionid on $pagename: I already reverted the page 3 times in the last 30 hours, please check [$link]."); } elsif ($safety_status eq 'HeavyEdit') { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Failed to revert edits by $user to $revisionid on $pagename: Page is heavily edited in the last 30 hours, please check manualy ( $diff ; $rule]."); $irc->yield(privmsg=>"#wikipedia-spam-t","ERROR: Failed to revert edits by $user to $revisionid on $pagename: Page is heavily edited in the last 30 hours, please check manualy ( $diff ; $rule]."); logit("ERROR: Failed to revert edits by $user to $revisionid on $pagename: Page is heavily edited in the last 30 hours, please check [$link]."); } elsif ($safety_status eq 'Reversion') { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Failed to revert to $revisionid on $pagename: Detected reversion ( $diff ; $rule]."); logit("ERROR: Failed to revert to $revisionid on $pagename: Detected reversion [$link]."); } } if ($revisionid==0) { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: An unknown error occurred in my revid retrieval function while reverting $user ( $diff ; $rule]."); logit("ERROR: An unknown error occurred in my revid retrieval function [$link]."); return; } } elsif ($settings{'reverting_on'}==0) { my $rule=$rules[0]; unless ($revisionid==0) { my $safety_status=check_if_safe($pagename,$user); if ($safety_status eq 'Pass') { $irc->yield(privmsg=>"#wikipedia-en-spam","Fake-reverted to $revisionid on $pagename ( $diff ; $rule]."); logit("Fake-reverted to $revisionid on $pagename ($diff) [$link]."); return; } elsif ($safety_status eq 'Fail') { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Failed to fake-revert to $revisionid on $pagename: Someone has edited since the spammer ( $diff ; $rule]."); logit("ERROR: Failed to fake-revert to $revisionid on $pagename: Someone has edited since the spammer ($diff) [$link]."); return; } elsif ($safety_status eq 'Alreadydid') { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Failed to fake-revert to $revisionid on $pagename: I've already reverted ( $diff ; $rule]."); logit("ERROR: Failed to fake-revert to $revisionid on $pagename: I've already reverted ($diff) [$link]."); } elsif ($safety_status eq 'Reversion') { $irc->yield(privmsg=>"#wikipedia-en-spam","ERROR: Failed to fake-revert to $revisionid on $pagename: Detected reversion ( $diff ; $rule]."); logit("ERROR: Failed to fake-revert to $revisionid on $pagename: Detected reversion ($diff) [$link]."); } } } } sub check_if_safe { my $pagename = shift; my $user = shift; my $override = shift; my $hard_override = shift; my $revisionid = shift; my $rule = shift; my @history=$editor->get_history($pagename,50); print "Last user on $pagename is " . $history[0]->{user} . "\n"; unless (($history[0]->{user}) eq $user) { return 'Fail'; } if (($history[1]->{user}) eq $username) { unless($settings{'revert_once'}==0 || $override==1 || $hard_override==1) {return 'Alreadydid';} } if (($history[1]->{user}) =~m/($settings{'AntiVandalismBots'})/) { unless($settings{'revert_once'}==0 || $override==1 || $hard_override==1) {return 'AntiVandalismBot';} } if (($history[0]->{comment})=~m/\b(rvv|rv|revert|reverting|VP2|rvt|reverted|reversion|robot|bot|rollback|roll back|rolling back|rolled back|undid|undo)\b/i) { unless($settings{'revert_once'}==0 || $override==1 || $hard_override==1) {return 'Reversion';} } my $count = 0; my $reverttime; my $timediff; foreach my $hist (@history) { if ($hist->{user} eq $username) { $reverttime=str2time("$hist->{timestamp_date} $hist->{timestamp_time}"); $timediff = time() - $reverttime; print ("I already reverted today, U: $username, W: $hist->{user}, TS: $hist->{timestamp_date} $hist->{timestamp_time}, RT: $reverttime, TD: $timediff.\n"); if ($timediff < $settings{'3RR_Reverttime'}) { $count = $count + 1; } } } $reverttime=str2time($hist->{timestamp}); $timediff = time() - $reverttime; if ($count >$settings{'3RR_Reverts'} ) { unless($settings{'revert_once'}==0 || $hard_override==1) {return '3RR';} } elsif (($timediff < (60 * 60 * 30)) && ($count > 0)) { unless($settings{'revert_once'}==0 || $hard_override==1) {return 'HeavyEdit';} } return 'Pass'; } sub warn_user { my $user=shift; my $diffurl=shift; my $pagename=shift; my $rule=shift; my $time=time(); my $summary=''; my $exists=check_mysql("users",$user); unless ($exists) { insert_mysql("users",$user,$time,"1"); } print ("Warning user $user for $diffurl.\n"); my $sql="SELECT * FROM users WHERE user_name=" . $mysql_handle->quote($user); my $sql_results=select_mysql($sql); my $lasttime=@{$sql_results}[0]->{user_time}; my $warninglevel=@{$sql_results}[0]->{user_level}; if (($time-$lasttime)>14400) { $warninglevel=1; } if ($warninglevel==1) { $talk_page="{{subst:uw-spam1|$pagename| }}"; } elsif ($warninglevel==2) { $talk_page="{{subst:uw-spam2|$pagename| }}"; } elsif ($warninglevel==3) { $talk_page="{{subst:uw-spam3|$pagename| }}"; } elsif ($warninglevel==4) { $talk_page="{{subst:uw-spam4|$pagename| }}"; } if (($warninglevel < 5) && ($warninglevel >0)) { $talk_page.="\n:Your edit [$diffurl here] was reverted by an automated bot that attempts to remove [[WP:NOT#REPOSITORY|unwanted links]] and [[WP:SPAM|spam]] from Wikipedia. If you were trying to insert a good link, please accept my creator's apologies, but note that the [[Wikipedia:External links|external link]] you added or changed is on my list of links to remove and probably shouldn't be included in Wikipedia.\n:The external links I reverted were matching the following [[regex|regex rule(s)]]: $rule."; } my $found = 0; my $query_handle=$mysql_handle->prepare("SELECT rule FROM media"); $query_handle->execute; while (my $data=$query_handle->fetchrow_array) { if($rule=~m/$data/) { $found = 1; } } if (($found) && (($warninglevel < 5) && ($warninglevel >0))) { $talk_page.=" If the external link you inserted or changed was to a [[Wikipedia:Media|media]] file (e.g. an [[Wikipedia:Images|image]] or a [[Wikipedia:Media help|sound or video]] file) on an external server, then note that linking to such files may be subject to Wikipedia's [[WP:COPYRIGHT|copyright policy]] and therefore probably should not be linked to. Please consider using our [[Wikipedia:Upload|upload]] facility to upload a suitable media file."; } my $found = 0; my $query_handle=$mysql_handle->prepare("SELECT rule FROM petition"); $query_handle->execute; while (my $data=$query_handle->fetchrow_array) { if($rule=~m/$data/) { $found = 1; } } if (($found) && (($warninglevel < 5) && ($warninglevel >0))) { $talk_page.=" If the external link you inserted or changed was to a [[petition]] site then please note that wikipedia is [[WP:SOAPBOX|not a soapbox]], and that such links generally should not be included."; } my $found = 0; my $query_handle=$mysql_handle->prepare("SELECT rule FROM freehost"); $query_handle->execute; while (my $data=$query_handle->fetchrow_array) { if($rule=~m/$data/) { $found = 1; } } if (($found) && (($warninglevel < 5) && ($warninglevel >0))) { $talk_page.=" If the external link you inserted or changed was to a [[blog]], [[forum]], [[free web hosting service]], or similar site, then please check the information on the external site thorougly. Note that such sites should probably not be linked to if they contain information that is in violation of the creators [[Wikipedia:COPYRIGHT|copyright]] (see [[Wikipedia:COPYRIGHT#Linking to copyrighted works|Linking to copyrighted works]]), or they are not written by a recognised, [[Wikipedia:Reliable sources|reliable source]]. Linking to sites that you are involved with is also strongly discouraged (see [[Wikipedia:Conflict of interest|conflict of interest]])."; } my $found = 0; my $query_handle=$mysql_handle->prepare("SELECT rule FROM payperview"); $query_handle->execute; while (my $data=$query_handle->fetchrow_array) { if($rule=~m/$data/) { $found = 1; } } if (($found) && (($warninglevel < 5) && ($warninglevel >0))) { $talk_page.=" If the external link you inserted or changed was to a site that provides payment for people visiting the that page, then note that Wikipedia is not an [[Wikipedia:Spam|advertising service]]. Linking to sites that you are involved with is also strongly discouraged (see [[Wikipedia:Conflict of interest|conflict of interest]])."; } if (($warninglevel < 5) && ($warninglevel >0)) { $talk_page.="\n:Please read Wikipedia's [[WP:EL|external links guideline]] for more information, and consult my [[User:$username/Reversion reasons|list of frequently-reverted sites]]. For more information about me, see [[User:$username/FAQ|my FAQ page]]. Thanks! ~~~~"; } if (($user =~ m/\d+\.\d+\.\d+\.\d+/) && (($warninglevel < 5) && ($warninglevel >0))) { $talk_page.="\n:<small>If this is a shared [[IP address]], and you didn't make the edit, please ignore this notice.</small>"; } if ($warninglevel==5) { my $message; $irc->yield(privmsg=>"#wikipedia-en-spam"=>"!admin ALERT: [[:en:User:$user]]/[[:en:Special:Contributions/$user]] has spammed past their final warning (level $warninglevel)."); $irc->yield(privmsg=>"#wikipedia-spam-t"=>"!admin ALERT: [[:en:User:$user]]/[[:en:Special:Contributions/$user]] has spammed past their final warning (level $warninglevel)."); if ($user =~ m/\d+\.\d+\.\d+\.\d+/) { $message="{{IPvandal|$user}} Has spammed after final warning. ~~~~"; } else { $message="{{vandal|$user}} Has spammed after final warning. ~~~~"; } my $text=$editor->get_text("Wikipedia:Administrator_intervention_against_vandalism/TB2"); $text .="\n$message"; $editor->edit("Wikipedia:Administrator_intervention_against_vandalism/TB2",$text,"Reporting persistent spammer"); print "$user posted to AIV.\n"; $irc->yield(ctcp=>"#wikipedia-spam-t"=>"ACTION dances."); } if ($warninglevel<5) { print ("Putting warning on talkpage user $user for $diffurl.\n"); my $user_talkpage=$editor->get_text("User_talk:$user"); my ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = gmtime(time()); my @months = qw(January February March April May June July August September October November December); $year = $yearOffset + 1900; my $date = "$months[$month] $year"; unless ($user_talkpage =~ m/$date/) { $user_talkpage .= "\n=== $date ==="; } $user_talkpage.="\n$talk_page"; my $editsummary = "BOT - Notifying $user of reverted changes to [[$pagename]]"; if ($warninglevel == 1) { $editsummary .= " (first warning)"; } elsif ($warninglevel == 2) { $editsummary .= " (second warning)"; } elsif ($warninglevel == 3) { $editsummary .= " (third warning)"; } elsif ($warninglevel == 4) { $editsummary .= " (fourth warning)"; } $editor->edit("User_talk:$user",$user_talkpage,$editsummary); print "Warned $user with {{tl|uw-spam" . $warninglevel . "}}.\n"; } $irc->yield(privmsg=>"#wikipedia-en-spam"=>"Warned user [[:en:User:$user]] (warninglevel $warninglevel).") unless ($warninglevel == 5); $warninglevel++; update_mysql("users","user_name=$user","user_time=$time","user_level=$warninglevel"); } sub select_mysql { my $query=shift; my $query_handle=$mysql_handle->prepare($query); $query_handle->execute; my $results=$query_handle->fetchall_arrayref({}); $query_handle->finish; return $results; } sub insert_mysql { my $table=shift; my @values = @_; my $query="INSERT INTO $table VALUES ("; foreach $value (@values) { $value=$mysql_handle->quote($value); $query.="$value,"; } $query=~s/,$//; $query.=")"; my $query_handle=$mysql_handle->prepare($query); $query_handle->execute; $query_handle->finish; } sub query_mysql { my $query=shift; my $query_handle=$mysql_handle->prepare($query); $query_handle->execute; $query_handle->finish; } sub update_mysql { my $table=shift; my $where=shift; my @updates=@_; my $updates; foreach $entry (@updates) { my ($field,$new_value)=split(/=/,$entry); $new_value=$mysql_handle->quote($new_value); $updates.="$field=$new_value,"; } $updates=~s/,$//; my ($where_field,$where_value)=split(/=/,$where); $where_value=$mysql_handle->quote($where_value); my $query="UPDATE $table SET $updates WHERE $where_field=$where_value"; my $query_handle=$mysql_handle->prepare($query); $query_handle->execute; $query_handle->finish; } sub check_mysql { my $table=shift; my $value=shift; my $query="SELECT * FROM $table WHERE "; if ($table eq 'authorized_bots') { $query.="bot_name="; } elsif ($table eq 'trusted_users') { $query.="user_cloak="; } elsif ($table eq 'blacklist' || $table eq 'quarantine' || $table eq 'overrides' || $table eq 'rules_stats' | $table eq 'watched_rules' | $table eq 'autoconfirm' || $table eq 'hard_overrides') { $query.="rule="; } elsif ($table eq 'users') { $query.="user_name="; } $value=$mysql_handle->quote($value); $query.="$value"; my $query_handle=$mysql_handle->prepare($query); $query_handle->execute; my $result=undef; if ($query_handle->rows > 0) { $result=1; } return $result; } sub set_override { my $rule=shift; my $option=shift; $rule=$mysql_handle->quote($rule); my $query; if ($option==1) { $query="INSERT INTO overrides VALUES($rule)"; } else {$query="DELETE FROM overrides WHERE rule=$rule";} my $query_handle=$mysql_handle->prepare($query); $query_handle->execute; $query_handle->finish; } sub update_rules_stats { my @rules=shift; foreach $rule (@rules) { my $query; my $exists=check_mysql("rules_stats",$rule); $rule=$mysql_handle->quote($rule); if (!$exists) { $query="INSERT INTO rules_stats VALUES($rule,1)"; } elsif ($exists) { $query="UPDATE rules_stats SET count=count + 1 WHERE rule=$rule"; } my $query_handle=$mysql_handle->prepare($query); $query_handle->execute; $query_handle->finish; } } sub logit { my $message = shift; $message=$mysql_handle->quote($message); my $query="INSERT INTO log VALUES(DEFAULT,$message)"; my $query_handle=$mysql_handle->prepare($query); $query_handle->execute; $query_handle->finish; } sub extract_mysql { my $table=shift; my $criteria=shift; my @results; my $query_handle=$mysql_handle->prepare("SELECT * FROM $table WHERE $criteria"); $query_handle->execute; my $data=$query_handle->fetchall_arrayref({}); foreach my $row (@$data) { push (@results,$row); } $query_handle->finish; return @results; } sub irc_msg { my ($kernel,$sender,$nick,$message)=@_[KERNEL,SENDER,ARG0,ARG2]; my $cloak=(split /@/, $nick)[1]; if ($cloak eq 'wikimedia/shadow42') { print "Received private message from user cloak $cloak.\n"; if ($message=~m/(.+?) (.+)/) { my $channel=$1; my $to_send=$2; $irc->yield(privmsg=>$channel=>$to_send); print "Sending text \"$to_send\" to channel $channel\n"; } } } sub autoconfirm { my $user=shift; my $user_log=$editor->{mech}->get("http://en.wikipedia.org/w/index.php?title=Special:Log&type=newusers&user=$user&page=&pattern=&limit=500&offset=0")->decoded_content; my $age="00:00, 1 January 1970"; if ($user_log=~m/<li>(.+?)\s?<.+?\Q$user\E.+?New user account.+?<\/li>/) { $age=$1; } my $current_time=time(); $age=str2time($age); $age=$current_time-$age; return $age; }