User:Blow of Light/monobook.css
From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. In Internet Explorer and Firefox, hold down the Ctrl key and click the Refresh or Reload button. Opera users have to clear their caches through Tools→Preferences, see the instructions for Opera. Konqueror and Safari users can just click the Reload button.
<?PHP class http { private $ch; private $uid; function data_encode ($data, $keyprefix = "", $keypostfix = "") { assert( is_array($data) ); $vars=null; foreach($data as $key=>$value) { if(is_array($value)) $vars .= $this->data_encode($value, $keyprefix.$key.$keypostfix.urlencode("["), urlencode("]")); else $vars .= $keyprefix.$key.$keypostfix."=".urlencode($value)."&"; } return $vars; } function __construct () { $this->ch = curl_init(); $this->uid = dechex(rand(0,99999999)); curl_setopt($this->ch,CURLOPT_COOKIEJAR,'/tmp/cluewikibot.cookies.'.$this->uid.'.dat'); curl_setopt($this->ch,CURLOPT_COOKIEFILE,'/tmp/cluewikibot.cookies.'.$this->uid.'.dat'); curl_setopt($this->ch,CURLOPT_MAXCONNECTS,100); curl_setopt($this->ch,CURLOPT_CLOSEPOLICY,CURLCLOSEPOLICY_LEAST_RECENTLY_USED); } function post ($url,$data) { // echo 'POST: '.$url."\n"; $time = microtime(1); curl_setopt($this->ch,CURLOPT_URL,$url); curl_setopt($this->ch,CURLOPT_FOLLOWLOCATION,1); curl_setopt($this->ch,CURLOPT_MAXREDIRS,10); curl_setopt($this->ch,CURLOPT_HEADER,0); curl_setopt($this->ch,CURLOPT_RETURNTRANSFER,1); curl_setopt($this->ch,CURLOPT_TIMEOUT,30); curl_setopt($this->ch,CURLOPT_CONNECTTIMEOUT,10); curl_setopt($this->ch,CURLOPT_POST,1); curl_setopt($this->ch,CURLOPT_POSTFIELDS, substr($this->data_encode($data), 0, -1) ); $data = curl_exec($this->ch); echo 'POST: '.$url.' ('.(microtime(1) - $time)." s)\n"; return $data; } function get ($url) { //echo 'GET: '.$url."\n"; $time = microtime(1); curl_setopt($this->ch,CURLOPT_URL,$url); curl_setopt($this->ch,CURLOPT_FOLLOWLOCATION,1); curl_setopt($this->ch,CURLOPT_MAXREDIRS,10); curl_setopt($this->ch,CURLOPT_HEADER,0); curl_setopt($this->ch,CURLOPT_RETURNTRANSFER,1); curl_setopt($this->ch,CURLOPT_TIMEOUT,30); curl_setopt($this->ch,CURLOPT_CONNECTTIMEOUT,10); curl_setopt($this->ch,CURLOPT_HTTPGET,1); $data = curl_exec($this->ch); echo 'GET: '.$url.' ('.(microtime(1) - $time).' s)'."\n"; return $data; } function __destruct () { curl_close($this->ch); @unlink('/tmp/cluewikibot.cookies.'.$this->uid.'.dat'); } } class wikipediaquery { private $http; public $queryurl = 'http://en.wikipedia.org/w/query.php'; function __construct () { global $__wp__http; if (!isset($__wp__http)) { $__wp__http = new http; } $this->http = &$__wp__http; } function getpage ($page) { $ret = unserialize($this->http->get($this->queryurl.'?what=content&format=php&titles='.urlencode($page))); foreach ($ret['pages'] as $page) { return $page['content']['*']; } } function getpageid ($page) { $ret = unserialize($this->http->get($this->queryurl.'?what=content&format=php&titles='.urlencode($page))); foreach ($ret['pages'] as $page) { return $page['id']; } } function contribcount ($user) { $ret = unserialize($this->http->get($this->queryurl.'?what=contribcounter&format=php&titles=User:'.urlencode($user))); foreach ($ret['pages'] as $page) { return $page['contribcounter']['count']; } } } class wikipediaapi { private $http; public $apiurl = 'http://en.wikipedia.org/w/api.php'; function __construct () { global $__wp__http; if (!isset($__wp__http)) { $__wp__http = new http; } $this->http = &$__wp__http; } function login ($user,$pass) { $this->http->post($this->apiurl.'?action=login',array('lgname' => $user, 'lgpassword' => $pass)); } function recentchanges ($count = 10,$namespace = null,$dir = 'older',$ts = null) { $append = ''; if ($ts !== null) { $append .= '&rcstart='.urlencode($ts); } $append .= '&rcdir='.urlencode($dir); if ($namespace !== null) { $append .= '&rcnamespace='.urlencode($namespace); } $x = $this->http->get($this->apiurl.'?action=query&list=recentchanges&rcprop=user|comment|flags|timestamp|title|ids|sizes&format=php&rclimit='.$count.$append); $x = unserialize($x); return $x['query']['recentchanges']; } function usercontribs ($user,$count = 50,$continue = null,$dir = 'older') { if ($continue != null) { $append = '&ucstart='.urlencode($continue); } else { $append = ''; } $x = $this->http->get($this->apiurl.'?action=query&format=php&list=usercontribs&ucuser='.urlencode($user).'&uclimit='.urlencode($count).'&ucdir='.urlencode($dir).$append); $x = unserialize($x); return $x['query']['usercontribs']; } function revisions ($page,$count = 1,$dir = 'older',$content = false,$revid = null,$wait = true) { $x = $this->http->get($this->apiurl.'?action=query&prop=revisions&titles='.urlencode($page).'&rvlimit='.urlencode($count).'&rvprop=timestamp|ids|user|comment'.(($content)?'|content':'').'&format=php&rvdir='.urlencode($dir).(($revid !== null)?'&rvstartid='.urlencode($revid):'')); $x = unserialize($x); if ($revid !== null) { $found = false; if (!isset($x['query']['pages']) or !is_array($x['query']['pages'])) die(); foreach ($x['query']['pages'] as $data) { if (!isset($data['revisions']) or !is_array($data['revisions'])) die(); foreach ($data['revisions'] as $data2) if ($data2['revid'] == $revid) $found = true; unset($data,$data2); break; } if ($found == false) { if ($wait == true) { sleep(1); return $this->revisions($page,$count,$dir,$content,$revid,false); } else { die('Revision error.'."\n"); } } } foreach ($x['query']['pages'] as $data) { return $data['revisions']; } } function categorymembers ($category,$count = 500,$continue = null) { if ($continue != null) { $append = '&cmcontinue='.urlencode($continue); } else { $append = ''; } $x = $this->http->get($this->apiurl.'?action=query&list=categorymembers&cmcategory='.urlencode($category).'&format=php&cmlimit='.$count.$append); $x = unserialize($x); return $x['query']['categorymembers']; } function backlinks ($page,$count = 500,&$continue = null) { if ($continue != null) { $append = '&blcontinue='.urlencode($continue); } else { $append = ''; } $x = $this->http->get($this->apiurl.'?action=query&list=backlinks&bltitle='.urlencode($page).'&format=php&bllimit='.$count.$append); $x = unserialize($x); $continue = $x['query-continue']['backlinks']['blcontinue']; return $x['query']['backlinks']; } function embeddedin ($page,$count = 500,&$continue = null) { if ($continue != null) { $append = '&eicontinue='.urlencode($continue); } else { $append = ''; } $x = $this->http->get($this->apiurl.'?action=query&list=embeddedin&eititle='.urlencode($page).'&format=php&eilimit='.$count.$append); $x = unserialize($x); $continue = $x['query-continue']['embeddedin']['eicontinue']; return $x['query']['embeddedin']; } function listprefix ($prefix,$namespace = 0,$count = 500,$continue = null) { $append = '&apnamespace='.urlencode($namespace); if ($continue != null) { $append .= '&apfrom='.urlencode($continue); } $x = $this->http->get($this->apiurl.'?action=query&list=allpages&apprefix='.urlencode($prefix).'&format=php&aplimit='.$count.$append); $x = unserialize($x); return $x['query']['allpages']; } } class wikipediaindex { private $http; public $indexurl = 'http://en.wikipedia.org/w/index.php'; private $postinterval = 0; private $lastpost; function __construct () { global $__wp__http; if (!isset($__wp__http)) { $__wp__http = new http; } $this->http = &$__wp__http; } function post ($page,$data,$summery = '',$minor = false) { global $user; global $maxlag; global $irc; global $irctechchannel; global $run; global $maxlagkeepgoing; // if ((time() - $this->lastpost) < $this->postinterval) { // sleep($this->postinterval - (time() - $this->lastpost)); // } /* Slightly more effecient than sleeping 30 seconds after each post. */ $html = $this->http->get($this->indexurl.'?title='.urlencode($page).'&action=edit&maxlag='.urlencode($maxlag)); if (preg_match('/Waiting for ([^ ]*): ([0-9.-]+) seconds lagged/',$html,$lagged)) { if (is_resource($irc)) { foreach(explode(',',$irctechchannel) as $y) { fwrite($irc,'PRIVMSG '.$y.' :'.$lagged[1].' is lagged out by '.$lagged[2].' seconds. ('.$lagged[0].')'."\n"); } } sleep(10); if ($maxlagkeepgoing != true) { return false; } else { $html = $this->http->get($this->indexurl.'?title='.urlencode($page).'&action=edit'); } } /* If server is lagged, wait 10 seconds, then return false. */ if (preg_match('/'.preg_quote('{{nobots}}','/').'/i',$html)) { return false; } /* Honor the bots flags */ if (preg_match('/'.preg_quote('{{bots|allow=none}}','/').'/i',$html)) { return false; } if (preg_match('/'.preg_quote('{{bots|deny=all}}','/').'/i',$html)) { return false; } if (preg_match('/'.preg_quote('{{bots|deny=','/').'(.*)'.preg_quote('}}','/').'/i',$html,$m)) { if (in_array(explode(',',$m[1]),$user)) { return false; } } /* /Honor the bots flags */ if (!preg_match('/'.preg_quote($user,'/').'/i',$html)) { return false; } /* We need to be logged in */ // if (preg_match('/'.preg_quote('You have new messages','/').'/i',$html)) { return false; } /* Check talk page */ $wpq = new wikipediaquery; $wpq->queryurl = str_replace('index.php','query.php',$this->indexurl); // preg_match('/([0-9a-f]{32})/i',$wpq->getpage('User:'.$user.'/FalsePositives/md5'),$m); /* Check the false positives page */ // if (strtolower($m[1]) == strtolower(md5($wpq->getpage('User:'.$user.'/FalsePositives')))) { return false; } if (!preg_match('/(yes|enable|true)/i',((isset($run))?$run:$wpq->getpage('User:'.$user.'/Run')))) { return false; } /* Check /Run page */ $x = $this->forcepost($page,$data,$summery,$minor,$html); /* Go ahead and post. */ $this->lastpost = time(); return $x; } function forcepost ($page,$data,$summery = '',$minor = false,$edithtml = null) { $post['wpSection'] = ''; $post['wpScrolltop'] = ''; if ($minor == true) { $post['wpMinoredit'] = 1; } $post['wpTextbox1'] = $data; $post['wpSummary'] = $summery; if ($edithtml == null) { $html = $this->http->get($this->indexurl.'?title='.urlencode($page).'&action=edit'); } else { $html = $edithtml; } preg_match('|\<input type\=\\\'hidden\\\' value\=\"(.*)\" name\=\"wpStarttime\" /\>|U',$html,$m); $post['wpStarttime'] = $m[1]; preg_match('|\<input type\=\\\'hidden\\\' value\=\"(.*)\" name\=\"wpEdittime\" /\>|U',$html,$m); $post['wpEdittime'] = $m[1]; preg_match('|\<input type\=\\\'hidden\\\' value\=\"(.*)\" name\=\"wpEditToken\" /\>|U',$html,$m); $post['wpEditToken'] = $m[1]; preg_match('|\<input name\=\"wpAutoSummary\" type\=\"hidden\" value\=\"(.*)\" /\>|U',$html,$m); $post['wpAutoSummary'] = $m[1]; return $this->http->post($this->indexurl.'?title='.urlencode($page).'&action=submit',$post); } } ?> [edit] Diff function (diff.function.php) <?PHP function diff ($old,$new,$nret = true,$inline = false) { // if ($inline) { // return str_replace(array("\n",chr(92).chr(92),'\n'),array(' ',chr(92),"\n"),diff(implode("\n",explode(' ',str_replace(array(chr(92),"\n"),array(chr(92).chr(92),'\n'),$old))),implode("\n",explode(' ',str_replace(array(chr(92),"\n"),array(chr(92).chr(92),'\n'),$new))),$nret,false)); // } $file1 = tempnam('/tmp','diff_'); $file2 = tempnam('/tmp','diff_'); file_put_contents($file1,$old); file_put_contents($file2,$new); $out = array(); if ($inline) { // echo 'EXEC: wdiff -3'.(($nret)?'1':'2').' '.escapeshellarg($file1).' '.escapeshellarg($file2)."\n"; @exec('wdiff -3'.(($nret)?'1':'2').' '.escapeshellarg($file1).' '.escapeshellarg($file2),$out); foreach ($out as $key => $line) { if ($line == '======================================================================') unset($out[$key]); elseif ($nret) $out[$key] = '> '.$line; else $out[$key] = '< '.$line; } } else { @exec('diff -d --suppress-common-lines '.escapeshellarg($file1).' '.escapeshellarg($file2),$out); } $out2 = array(); foreach ($out as $line) { if ( ( ($nret) and (preg_match('/^\> .*$/',$line)) ) or ( (!$nret) and (preg_match('/^\< .*$/',$line)) ) ) { $out2[] = substr($line,2); } } $out = $out2; unset($out2); unlink($file1); unlink($file2); return implode("\n",$out); } ?> [edit] Source to ClueBot <?PHP declare(ticks = 1); function sig_handler($signo) { switch ($signo) { case SIGCHLD: while (($x = pcntl_waitpid(0, $status, WNOHANG)) != -1) { if ($x == 0) break; $status = pcntl_wexitstatus($status); } break; } } pcntl_signal(SIGCHLD, "sig_handler"); function score ($list,$data) { $ret = 0; foreach ($list as $preg => $pts) { if ($x = preg_match_all($preg,$data,$m)) { // echo $x.'*'.$pts.' ('.$preg.')'."\n"; $ret += $pts * $x; } } // echo 'Score: '.$ret."\n"; return $ret; } include '../diff.function.php'; /* The diff function. */ include '../wikibot.classes.php'; /* The wikipedia classes. */ include 'cluebot.config.php'; /* This file is very simple, but it contains sensitive information, we just define $user, $ircserver, $ircport, $ircchannel, $pass, $owner, and $status. */ include 'cluebot.scorelist.php'; /* This file is uploaded as well as the main file. */ $wpapi = new wikipediaapi; $wpq = new wikipediaquery; $wpi = new wikipediaindex; $wpapi->login($user,$pass); $mysql = mysql_pconnect($mysqlhost.':'.$mysqlport,$mysqluser,$mysqlpass); if (!$mysql) { die('Could not connect: ' . mysql_error()); } if (!mysql_select_db($mysqldb, $mysql)) { die ('Can\'t use database : ' . mysql_error()); } $ircconfig = explode("\n",$wpq->getpage('User:'.$owner.'/CBChannels.js')); $tmp = array(); foreach($ircconfig as $tmpline) { if (substr($tmpline,0,1) != '#') { $tmpline = explode('=',$tmpline,2); $tmp[trim($tmpline[0])] = trim($tmpline[1]); } } $ircchannel = $tmp['ircchannel']; $ircdebugchannel = $tmp['ircdebugchannel']; $ircreportchannel = $tmp['ircreportchannel']; $ircvandalismchannel = $tmp['ircvandalismchannel']; $ircaivchannel = $tmp['ircaivchannel']; $irctechchannel = $tmp['irctechchannel']; $ircproxychannels = $tmp['ircproxychannels']; $ircunrevertedchannels = $tmp['ircunrevertedchannels']; $ircbagtrialchannels = $tmp['ircbagtrialchannels']; $ircotherchannels = $tmp['ircotherchannels']; unset($tmp,$tmpline); $stalkbots = array(); $trialbots = explode("\n",$wpq->getpage('Wikipedia:Bots/Requests for approval')); foreach ($trialbots as $trialbot) if (preg_match('/\{\{BRFA\|(.*)\|.*\|Trial\}\}/',str_replace(array("\n","\r"),'',$trialbot),$m)) $stalkbots[$m[1]] = 1; $irc = fsockopen($ircserver,$ircport,$ircerrno,$ircerrstr,15); $ircpid = pcntl_fork(); if ($ircpid == 0) { fwrite($irc,'PASS '.$ircpass."\n"); fwrite($irc,'USER '.$user.' "1" "1" :ClueBot Wikipedia Bot.'."\n"); fwrite($irc,'NICK '.$user."\n"); while (!feof($irc)) { $data = str_replace(array("\n","\r"),'',fgets($irc,1024)); // echo 'IRC: '.$data."\n"; $d = explode(' ',$data); if (strtolower($d[0]) == 'ping') { fwrite($irc,'PONG '.$d[1]."\n"); } elseif (($d[1] == '376') or ($d[1] == '422')) { // fwrite($irc,'PRIVMSG NickServ :identify '.$pass."\n"); // sleep(2); fwrite($irc,'JOIN '.$ircchannel.','.$ircdebugchannel.','.$ircreportchannel.','.$ircvandalismchannel.','.$ircaivchannel.','.$irctechchannel.','.$ircproxychannels.','.$ircunrevertedchannels.','.$ircbagtrialchannels.','.$ircotherchannels."\n"); foreach (explode(',',$ircchannel) as $y) { fwrite($irc,'PRIVMSG '.$y.' :IRC logging enabled.'."\n"); } } elseif (strtolower($d[1]) == 'privmsg') { if (substr($d[3],0,2) == ':!') { if (strtolower($d[2]) == '#wikipedia-en') { $tmp = explode('!',substr($d[0],1)); $cmd = 'NOTICE '.$tmp[0]; } elseif (strtolower($d[2]) == strtolower($user)) { $tmp = explode('!',substr($d[0],1)); $cmd = 'NOTICE '.$tmp[0]; } else { $cmd = 'PRIVMSG '.$d[2]; } switch (substr(strtolower($d[3]),2)) { case 'edit': if (preg_match("/\[\[(.*)\]\]/",$data,$m)) { $rv = $wpapi->revisions($m[1],1,'older'); fwrite($irc,$cmd.' :[['.$m[1].']] http://en.wikipedia.org/w/index.php?title='.urlencode($m[1]).'&;diff=prev' . '&oldid='.urlencode($rv[0]['revid']).' * '.$rv[0]['user'].' * '.$rv[0]['comment']."\n"); } else { fwrite($irc,$cmd.' :Couldn\'t find link.'."\n"); } break; case 'stalk': if (preg_match("/\[\[User:(.*)\]\]/",$data,$m)) { $uc = $wpapi->usercontribs($m[1],1); fwrite($irc,$cmd.' :[['.$uc[0]['title'].']] http://en.wikipedia.org/w/index.php?title='.urlencode($uc[0]['title']).'&;diff=prev' . '&oldid='.urlencode($uc[0]['revid']).' * '.$m[1].' * '.$uc[0]['comment']."\n"); } else { fwrite($irc,$cmd.' :Couldn\'t find link.'."\n"); } break; case 'beaten': if (preg_match("/\[\[User:(.*)\]\]/",$data,$m)) { if (!mysql_ping($mysql)) { $mysql = mysql_pconnect($mysqlhost.':'.$mysqlport,$mysqluser,$mysqlpass); mysql_select_db($mysqldb, $mysql); } $x = mysql_fetch_assoc(mysql_query('SELECT COUNT(`id`) AS `count` FROM `beaten` WHERE `user` = \''.mysql_real_escape_string($m[1]).'\' GROUP BY `user`')); $y = mysql_fetch_assoc(mysql_query('SELECT SQL_CALC_FOUND_ROWS COUNT(`id`) AS `count2` FROM `beaten` GROUP BY `user` HAVING `count2` > \''.mysql_real_escape_string($x['count']).'\' LIMIT 1')); $z = mysql_fetch_assoc(mysql_query('SELECT FOUND_ROWS() as `ahead`')); fwrite($irc,$cmd.' :[[User:'.$m[1].']] has beaten me '.(($x['count'] != '')?$x['count']:'0').' times. There are '.$z['ahead'].' users who have beaten me more times.'."\n"); unset($x,$y); } else { fwrite($irc,$cmd.' :Couldn\'t find link.'."\n"); } break; case 'vandalcount': if (preg_match("/\[\[(.*)\]\]/",$data,$m)) { $tmp = unserialize(file_get_contents('oftenvandalized.txt')); if (isset($tmp[$m[1]])) { fwrite($irc,$cmd.' :[['.$m[1].']] has been vandalized '.count($tmp[$m[1]]).' time(s) in the last 48 hours.'."\n"); } else { fwrite($irc,$cmd.' :[['.$m[1].']] has not been vandalized in the last 48 hours.'."\n"); } } else { fwrite($irc,$cmd.' :Couldn\'t find link.'."\n"); } break; case 'heuristics': include 'cluebot.heuristics.config.php'; $stats = unserialize(file_get_contents('cluebot.heuristics.stats.txt')); fwrite($irc,$cmd.' :I have the following heuristics enabled: '.implode(', ',$heuristics).".\n"); foreach ($stats as $heuristic => $count) { fwrite($irc,$cmd.' :The '.$heuristic.' heuristic has been matched '.$count.' times.'."\n"); } unset($count,$heuristic,$stats,$heuristics); break; case 'status': $ov = unserialize(file_get_contents('oftenvandalized.txt')); foreach ($ov as $title => $array) { if (count($array) == 0) unset($ov[$title]); } file_put_contents('oftenvandalized.txt',serialize($ov)); $count = count($ov); $titles = unserialize(file_get_contents('titles.txt')); foreach ($titles as $title => $time) { if ((time() - $time) > (24*60*60)) { unset($titles[$title]); } } file_put_contents('titles.txt',serialize($titles)); $tcount = count($titles); foreach ($ov as $x => $y) { $ocount[$x] = count($y); } arsort($ocount); foreach ($ocount as $x => $y) { $mova = $x; $movacount = $y; break; } preg_match('/\(\'\'\'\[\[([^|]*)\|more...\]\]\'\'\'\)/iU',$wpq->getpage('Wikipedia:Today\'s featured article/'.date('F j, Y')),$tfa); $tfa = $tfa[1]; if (!preg_match('/(yes|enable|true)/i',$wpq->getpage('User:'.$user.'/Run'))) { $run = false; } else { $run = true; } $top5beat = array(); if (!mysql_ping($mysql)) { $mysql = mysql_pconnect($mysqlhost.':'.$mysqlport,$mysqluser,$mysqlpass); mysql_select_db($mysqldb, $mysql); } $q = mysql_query('SELECT `user`,COUNT(`id`) AS `count` FROM `cluebot_enwiki`.`beaten` WHERE `user` != \'\' GROUP BY `user` HAVING `count` > 1 ORDER BY `count` DESC LIMIT 5'); while ($x = mysql_fetch_assoc($q)) { $top5beat[] = $x['user'].' ('.$x['count'].')'; } unset($x,$q); $top5beat = implode(' - ',$top5beat); fwrite($irc,$cmd.' :I am '.$user.'. I am currently '.($run?'enabled':'disabled').'. I currently have '.$wpq->contribcount($user).' contributions.'."\n"); fwrite($irc,$cmd.' :I have attempted to revert '.$tcount.' unique article/user combinations in the last 24 hours. ' . 'I know of '.$count.' different articles that have been vandalized in the last 48 hours.'."\n" ); fwrite($irc,$cmd.' :[['.$mova.']] is the most vandalized page with a total of '.$movacount.' vandalisms in the last 48 hours. ' . 'Today\'s featured article is: [['.$tfa.']].'."\n" ); fwrite($irc,$cmd.' :The following users have beat me to the revert the most: '.$top5beat."\n"); fwrite($irc,$cmd.' :I log all information to '.$ircchannel.'. This channel is '.$d[2].'.'."\n"); unset($x,$y,$count,$ov,$tcount,$ocount,$mova,$movacount,$tfa,$run,$title,$titles,$time,$top5beat); break; case 'warninglevel': if (preg_match("/\[\[User:(.*)\]\]/",$data,$n)) { $warning = 0; if (preg_match_all('/<!-- Template:(uw-[a-z]*(\d)(im)?|Blatantvandal \(serious warning\)) -->;.*(\d{2}):(\d{2}), (\d+) ([a-zA-Z]+) (\d{4}) \(UTC\)/iU', $wpq->getpage('User talk:'.$n[1]), $match,PREG_SET_ORDER) ) { foreach ($match as $m) { $month = array('January' => 1, 'February' => 2, 'March' => 3, 'April' => 4, 'May' => 5, 'June' => 6, 'July' => 7, 'August' => 8, 'September' => 9, 'October' => 10, 'November' => 11, 'December' => 12 ); if ($m[1] == 'Blatantvandal (serious warning)') $m[2] = 4; if ((time() - gmmktime($m[4],$m[5],0,$month[$m[7]],$m[6],$m[8])) <= (2*24*60*60)) { if ($m[2] > $warning) { $warning = $m[2]; } } } } fwrite($irc,$cmd.' :[[User:'.$n[1].']] is at warning level '.$warning.".\n"); } else { fwrite($irc,$cmd.' :Couldn\'t find link.'."\n"); } break; case 'count': if (preg_match("/\[\[User:(.*)\]\]/",$data,$n)) { fwrite($irc,$cmd.' :[[User:'.$n[1].']] has '.$wpq->;contribcount($n[1])." contributions.\n"); } else { fwrite($irc,$cmd.' :Couldn\'t find link.'."\n"); } break; case 'help': fwrite($irc,$cmd.' :Please see [[User:'.$user.']].'."\n"); break; case 'eval': $tmp = explode(' ',$data,6); $tmp1 = explode('!',substr($d[0],1)); if ($d[4] == md5($thesecret.$tmp1[0].$tmp[5])) { eval($tmp[5]); } else { fwrite($irc,$cmd.' :Code incorrect.'."\n"); } break; case 'cbproxy': $tmp = explode(' ',$data,6); $tmp1 = explode('!',substr($d[0],1)); if ($tmp1[0] == 'ClueBot-Bopm') { foreach (explode(',',$ircproxychannels) as $y) { fwrite($irc,'PRIVMSG '.$y.' :!admin '.$tmp[5]."\n"); } $data = $wpq->getpage('Wikipedia:WikiProject on open proxies'); if (strpos($data,$tmp[4]) === false) { $header = explode('{{proxyip2|127.0.0.1}} || Example',$data,2); $header[0] .= '{{proxyip2|127.0.0.1}} || Example '; $footer = $header[1]; $header = $header[0]; $data = "\n".'{{proxyip2|'.$tmp[4].'}} || '.$tmp[5].' <font face="Copperplate Gothic">[[User:Gp75motorsports|<font color="#FF0000">Gp</font><font color="#000000">75</font><font color="#FF0000">motorsports</font>]] <sup><font color="#800000">[[User talk:Gp75motorsports|REV LIMITER]]</font></sup></font> 22:39, 2 January 2008 (UTC)'."\n"; $data = $header.$data.$footer; unset($header,$footer); $wpi->post('Wikipedia:WikiProject on open proxies',$data,'Adding '.$tmp[4].'.'); unset($data); } } break; } } } } die(); } $heuristics = "==Heuristics==\n\n===Config (cluebot.heuristics.config.php)===\n\n<pre>".htmlentities(file_get_contents('cluebot.heuristics.config.php'))."</pre>\n\n"; foreach (glob('heuristics/cluebot.*.heuristic.php') as $heuristic) $heuristics .= '==='.$heuristic."===\n\n<pre>".htmlentities(file_get_contents($heuristic))."</pre>\n\n"; unset($heuristic); $wpi->forcepost('User:'.$user.'/Source', 'The following is automatically generated by [[User:'.$user.'|'.$user."]].\n\n\n\n==Classes (wikibot.classes.php)==\n\n<pre>" . htmlentities(file_get_contents('../wikibot.classes.php'))."</pre>\n\n\n\n==Diff function (diff.function.php)==\n\n<pre>" . htmlentities(file_get_contents('../diff.function.php'))."</pre>\n\n\n\n==Source to ".$user . "==\n\n".'<pre>'.htmlentities(file_get_contents(__FILE__))."</pre>\n\n\n\n" . $heuristics . "==Score list==\n\n".'<pre>'.htmlentities(file_get_contents('cluebot.scorelist.php'))."</pre>\n\n\n\n<font face="Copperplate Gothic">[[User:Gp75motorsports|<font color="#FF0000">Gp</font><font color="#000000">75</font><font color="#FF0000">motorsports</font>]] <sup><font color="#800000">[[User talk:Gp75motorsports|REV LIMITER]]</font></sup></font> 22:39, 2 January 2008 (UTC)", 'Automated source upload.'); /* Our source code, we force post this because this is *our* page, and it triggers the nobots. */ unset($heuristics); $wpi->forcepost('User:'.$user, "{{User:ClueBot Commons/Userpage}}\n", 'Automated bot userpage set.'); /* Our page, we force post this because this is *our* page. */ $tfas = 0; $pipe = fopen('thepipe','w'); $stdin = fopen('php://stdin','r'); $run = $wpq->getpage('User:'.$user.'/Run'); $wl = $wpq->getpage('User:'.$user.'/Whitelist'); $optin = $wpq->getpage('User:'.$user.'/Optin'); $aoptin = $wpq->getpage('User:'.$user.'/AngryOptin'); unset($tmp,$tmp2,$tmp3); $tmp = explode("\n",$wpq->getpage('User:'.$owner.'/CBAutostalk.js')); foreach ($tmp as $tmp2) { if (substr($tmp2,0,1) != '#') { $tmp3 = explode('|',$tmp2,2); $stalk[$tmp3[0]] = trim($tmp3[1]); } } $tmp = explode("\n",$wpq->getpage('User:'.$owner.'/CBAutoedit.js')); foreach ($tmp as $tmp2) { if (substr($tmp2,0,1) != '#') { $tmp3 = explode('|',$tmp2,2); $edit[$tmp3[0]] = trim($tmp3[1]); } } unset($tmp,$tmp2,$tmp3); print_r($stalk); print_r($edit); while (1) { $feed = fsockopen($feedhost,$feedport,$feederrno,$feederrstr,30); if (!$feed) { sleep(10); $feed = fsockopen($feedhost,$feedport,$feederrno,$feederrstr,30); if (!$feed) die($feederrstr.' ('.$feederrno.')'); } fwrite($feed,'USER '.$user.' "1" "1" :ClueBot Wikipedia Bot.'."\n"); fwrite($feed,'NICK '.$user."\n"); while (!feof($feed)) { $line = str_replace(array("\n","\r","\002"),'',fgets($feed,1024)); $line = preg_replace('/\003(\d\d?(,\d\d?)?)?/','',$line); // echo 'FEED: '.$line."\n"; if (!$line) { fclose($feed); break; } $linea= explode(' ',$line,4); if (strtolower($linea[0]) == 'ping') { fwrite($feed,'PONG '.$linea[1]."\n"); } elseif (($linea[1] == '376') or ($linea[1] == '422')) { fwrite($feed,'JOIN '.$feedchannel."\n"); } elseif ((strtolower($linea[1]) == 'privmsg') and (strtolower($linea[2]) == strtolower($feedchannel))) { $message = substr($linea[3],1); if (preg_match('/^\[\[((Talk|User|Wikipedia|Image|MediaWiki|Template|Help|Category|Portal|Special)(( |_)talk)?:)?([^\x5d]*)\]\] (\S*) (http:\/\/en\.wikipedia\.org\/w\/index\.php\?title=[^&;]*&diff=(\d*)&oldid=(\d*)|http:\/\/en\.wikipedia\.org\/wiki\/\S+)? \* ([^*]*) \* (\(([^)]*)\))? (.*)$/',$message,$m)) { $change['namespace'] = $m[1]; $change['title'] = $m[5]; $change['flags'] = $m[6]; $change['url'] = $m[7]; $change['revid'] = $m[8]; $change['old_revid'] = $m[9]; $change['user'] = $m[10]; $change['length'] = $m[12]; $change['comment'] = $m[13]; // include 'cluebot.stalk.config.php'; $stalkchannel = array(); foreach ($stalk as $key => $value) if (fnmatch(str_replace('_',' ',$key),str_replace('_',' ',$change['user']))) $stalkchannel = array_merge($stalkchannel,explode(',',$value)); foreach ($stalkbots as $key => $value) if (fnmatch(str_replace('_',' ',$key),str_replace('_',' ',$change['user']))) $stalkchannel = array_merge($stalkchannel,explode(',',$ircbagtrialchannels)); foreach ($edit as $key => $value) if (fnmatch(str_replace('_',' ',$key),str_replace('_',' ',$change['namespace'].$change['title']))) $stalkchannel = array_merge($stalkchannel,explode(',',$value)); // if ($change['user'] == $owner) $stalkchannel[] = $ircchannel; $stalkchannel = array_unique($stalkchannel); foreach ($stalkchannel as $y) { fwrite($irc,'PRIVMSG '.$y.' :New edit: [['.$change['namespace'].$change['title'].']] http://en.wikipedia.org/w/index.php?title=' . urlencode($change['namespace'].$change['title']).'&;diff=prev'.'&oldid='.urlencode($change['revid']).' * '.$change['user'] . ' * '.$change['comment']."\n"); } if (($change['namespace'] == 'User:') or ($change['namespace'] == 'User talk:')) { if (strtolower($change['title']) == strtolower($user.'/Run')) { $run = $wpq->getpage('User:'.$user.'/Run'); } if (strtolower($change['title']) == strtolower($user.'/Whitelist')) { $wl = $wpq->getpage('User:'.$user.'/Whitelist'); } if (strtolower($change['title']) == strtolower($user.'/Optin')) { $optin = $wpq->getpage('User:'.$user.'/Optin'); } if (strtolower($change['title']) == strtolower($user.'/AngryOptin')) { $aoptin = $wpq->getpage('User:'.$user.'/AngryOptin'); } if (strtolower($change['title']) == strtolower($owner.'/CBAutostalk.js')) { unset($stalk); $tmp = explode("\n",$wpq->getpage('User:'.$owner.'/CBAutostalk.js')); foreach ($tmp as $tmp2) { if (substr($tmp2,0,1) != '#') { $tmp3 = explode('|',$tmp2,2); $stalk[$tmp3[0]] = trim($tmp3[1]); } } unset($tmp,$tmp2,$tmp3); print_r($stalk); } if (strtolower($change['title']) == strtolower($owner.'/CBAutoedit.js')) { unset($edit); $tmp = explode("\n",$wpq->getpage('User:'.$owner.'/CBAutoedit.js')); foreach ($tmp as $tmp2) { if (substr($tmp2,0,1) != '#') { $tmp3 = explode('|',$tmp2,2); $edit[$tmp3[0]] = trim($tmp3[1]); } } unset($tmp,$tmp2,$tmp3); print_r($edit); } if (strtolower($change['title']) == strtolower($owner.'/CBChannels.js')) { $ircconfig = explode("\n",$wpq->getpage('User:'.$owner.'/CBChannels.js')); $tmp = array(); foreach($ircconfig as $tmpline) { if (substr($tmpline,0,1) != '#') { $tmpline = explode('=',$tmpline,2); $tmp[trim($tmpline[0])] = trim($tmpline[1]); } } print_r($tmp); $tmpold = array(); $tmpnew = array(); foreach ($tmp as $tmp2) foreach (explode(',',$tmp2) as $tmp3) $tmpnew[$tmp3] = 1; foreach (explode(',',$ircchannel.','.$ircdebugchannel.','.$ircreportchannel.','.$ircvandalismchannel.','.$ircaivchannel.','.$irctechchannel.','.$ircproxychannels.','.$ircunrevertedchannels.','.$ircbagtrialchannels.','.$ircotherchannels) as $tmp3) $tmpold[$tmp3] = 1; foreach ($tmpold as $tmp2 => $tmp3) if (isset($tmpnew[$tmp2])) unset($tmpold[$tmp2],$tmpnew[$tmp2]); foreach ($tmpnew as $tmp2 => $tmp3) $tmpnew1[] = $tmp2; foreach ($tmpold as $tmp2 => $tmp3) $tmpold1[] = $tmp2; $tmpold = $tmpold1; $tmpnew = $tmpnew1; unset($tmpold1,$tmpnew1); fwrite($irc,'JOIN '.implode(',',$tmpnew)."\n"); fwrite($irc,'PART '.implode(',',$tmpold)."\n"); $ircchannel = $tmp['ircchannel']; $ircdebugchannel = $tmp['ircdebugchannel']; $ircreportchannel = $tmp['ircreportchannel']; $ircvandalismchannel = $tmp['ircvandalismchannel']; $ircaivchannel = $tmp['ircaivchannel']; $irctechchannel = $tmp['irctechchannel']; $ircproxychannels = $tmp['ircproxychannels']; $ircunrevertedchannels = $tmp['ircunrevertedchannels']; $ircbagtrialchannels = $tmp['ircbagtrialchannels']; $ircotherchannels = $tmp['ircotherchannels']; unset($tmp,$tmpline,$tmpold,$tmpnew,$tmp2,$tmp3); } } if ($change['namespace'].$change['title'] == 'Wikipedia:Bots/Requests for approval') { $stalkbots = array(); $trialbots = explode("\n",$wpq->getpage('Wikipedia:Bots/Requests for approval')); foreach ($trialbots as $trialbot) if (preg_match('/\{\{BRFA\|(.*)\|.*\|Trial\}\}/',str_replace(array("\n","\r"),'',$trialbot),$m)) $stalkbots[$m[1]] = 1; } if (($change['namespace'] != '') and ((!preg_match('/\* \[\[('.preg_quote($change['namespace'].$change['title'],'/').')\]\] \- .*/i',$optin)))) { /* echo 'Continuing ...'."\n"; */ continue; } $change['justtitle'] = $change['title']; $change['title'] = $change['namespace'].$change['title']; if ( ((time() - $tfas) >= 1800) and (preg_match('/\(\'\'\'\[\[([^|]*)\|more...\]\]\'\'\'\)/iU',$wpq->getpage('Wikipedia:Today\'s featured article/'.date('F j, Y')),$tfam)) ) { $tfas = time(); $tfa = $tfam[1]; //echo "TFA: ".$tfa."\n"; } $s = null; $pid = @pcntl_fork(); if ($pid != 0) continue; $hutime = microtime(1); include 'cluebot.heuristics.config.php'; foreach ($heuristics as $heuristic) { $heuristicret = false; include 'heuristics/cluebot.'.$heuristic.'.heuristic.php'; if ($heuristicret == true) { $stats = unserialize(file_get_contents('cluebot.heuristics.stats.txt')); $stats[$heuristic]++; file_put_contents('cluebot.heuristics.stats.txt',serialize($stats)); unset($stats); break; } } if ($heuristicret == true) echo 'Heuristics time: '.(microtime(1) - $hutime)."\n"; unset($hutime); if ( ($heuristicret == true) ) { if ( ( ( /* IP users with 250 contributions are fine .. */ (long2ip(ip2long($change['user'])) == $change['user']) /* and ($uc = $wpapi->usercontribs($change['user'],250)) and (!isset($uc[249])) */ ) or ( /* Users with 50 contributions are fine .. */ (long2ip(ip2long($change['user'])) != $change['user']) and ($wpq->contribcount($change['user']) < 50) ) ) and ( /* Whitelisted users are ok. */ /* ($wl = $wpq->getpage('User:'.$user.'/Whitelist')) and */ (!preg_match('/^\* \[\[User:('.preg_quote($change['user'],'/').')|\1\]\] \- .*/',$wl)) ) ) { // $vandalpage = $wpq->;getpage('User:'.$user.'/PossibleVandalism'); // $x = explode("\n\n",$vandalpage); // foreach ($x as $k => $y) { // if (preg_match('/(\d+)\-(\d+)\-(\d+)T(\d+):(\d+):(\d+)/',$y,$m)) { // if ((time() - gmmktime($m[4],$m[5],$m[6],$m[2],$m[3],$m[1])) > (5*60*60)) { // unset($x[$k]); // } // } // } // $vandalpage = implode("\n\n",$x); $diff = 'http://en.wikipedia.org/w/index.php' . '?title='.urlencode($change['title']) . '&diff='.urlencode($change['revid']) . '&oldid='.urlencode($change['old_revid']); $report = '[['.$change['title'].']] was ' . '['.$diff.' changed] by ' . '[[User:'.$change['user'].'|'.$change['user'].']] ' . '[[Special:Contributions/'.$change['user'].'|(c)]] ' . '[[User talk:'.$change['user'].'|(t)]] ' . $reason.' on '.gmdate('c'); // $datatopost = $vandalpage."\n\n".'Possible [[WP:VAN|vandalism]]: '.$report." <font face="Copperplate Gothic">[[User:Gp75motorsports|<font color="#FF0000">Gp</font><font color="#000000">75</font><font color="#FF0000">motorsports</font>]] <sup><font color="#800000">[[User talk:Gp75motorsports|REV LIMITER]]</font></sup></font> 22:39, 2 January 2008 (UTC)\n"; if ($s == null) { // $rv = $wpapi->revisions($change['title'],2,'older',true,$change['revid']); // $s = score($scorelist,diff($rv[1]['*'],$rv[0]['*'])); // $s += (score($scorelist,diff($rv[1]['*'],$rv[0]['*'],false))) * -1; $s = 'N/A'; } $tmp = unserialize(file_get_contents('oftenvandalized.txt')); foreach ($tmp as $key1 => $tmp2) { foreach ($tmp2 as $key2 => $time) { if ((time() - $time) > (2*24*60*60)) { unset($tmp[$key1][$key2]); } } } $tmp[$change['title']][] = time(); if (count($tmp[$change['title']]) >= 30) { foreach (explode(',',$ircreportchannel) as $y) { fwrite($irc,'PRIVMSG '.$y.' :!admin [['.$change['title'].']] has been vandalized '.(count($tmp[$change['title']])).' times in the last 2 days.'."\n"); } } file_put_contents('oftenvandalized.txt',serialize($tmp)); if ( ($rv = $wpapi->revisions($change['title'],1,'older')) and ($rv[0]['revid'] == $change['revid']) ) { /* No need to continue further if it has been reverted */ echo 'Possible vandalism: '.$change['title'].' changed by '.$change['user'].' '.$reason.' on '.$rv[0]['timestamp'].'('.$s.").\n"; foreach (explode(',',$ircdebugchannel) as $y) { fwrite($irc,'PRIVMSG '.$y.' :Possible vandalism: '.$change['title'].' changed by '.$change['user'].' '.$reason.' on '.$rv[0]['timestamp'].'('.$s.").\n"); fwrite($irc,'PRIVMSG '.$y.' :( http://en.wikipedia.org/w/index.php?title='.urlencode($change['title']).'&;action=history | '.$change['url'].' )'."\n"); } fwrite($pipe,'http://en.wikipedia.org/w/index.php?title='.urlencode($change['title']).'&action=history'."\n"); /* Tell owner */ $mqtime = microtime(1); $query = 'INSERT INTO `vandalism` ' . '(`id`,`user`,`article`,`heuristic`,`reason`,`diff`,`old_id`,`new_id`,`reverted`) ' . 'VALUES ' . '(NULL,\''.mysql_real_escape_string($change['user']).'\',' . '\''.mysql_real_escape_string($change['title']).'\',' . '\''.mysql_real_escape_string($heuristic).'\',' . '\''.mysql_real_escape_string($reason).'\',' . '\''.mysql_real_escape_string($change['url']).'\',' . '\''.mysql_real_escape_string($change['old_revid']).'\',' . '\''.mysql_real_escape_string($change['revid']).'\',0)'; //echo 'Mysql query: '.$query."\n"; if (!mysql_ping($mysql)) { $mysql = mysql_pconnect($mysqlhost.':'.$mysqlport,$mysqluser,$mysqlpass); if (!$mysql) { die('Could not connect: ' . mysql_error()); } if (!mysql_select_db($mysqldb, $mysql)) { die ('Can\'t use database : ' . mysql_error()); } } mysql_query($query); //echo 'Mysql error: '.mysql_error()."\n"; $mysqlid = mysql_insert_id(); echo 'MySQL time: '.(microtime(1) - $mqtime).' MySQL id: '.$mysqlid."\n"; unset($mqtime); if ( ( ( (preg_match('/(assisted|manual)/i',$status)) and (print('Revert [y/N]? ')) and (strtolower(substr(fgets($stdin,3),0,1)) == 'y') ) or ( (preg_match('/(read-write|rw|go|approved|trial)/i',$status)) ) ) and ( ( ( ((time() - $tfas) < 1800) or ( (preg_match('/\(\'\'\'\[\[([^|]*)\|more...\]\]\'\'\'\)/iU',$wpq->getpage('Wikipedia:Today\'s featured article/'.date('F j, Y')),$tfam)) and ($tfas = time()) and ($tfa = $tfam[1]) and ((print("TFA: ".$tfa."\n")) or (true)) ) ) and ($tfa == $change['title']) ) or ( (preg_match('/\* \[\[('.preg_quote($change['title'],'/').')\]\] \- .*/i',$aoptin)) and ((fwrite($irc,'PRIVMSG '.$ircdebugchannel.' :Angry-reverting [['.$change['title'].']].'."\n")) or (true)) ) or ( (($tmp = unserialize(file_get_contents('titles.txt'))) !== false) and ((!isset($tmp[$change['title'].$change['user']])) or ((time() - $tmp[$change['title'].$change['user']]) > (24*60*60))) and ($tmp[$change['title'].$change['user']] = time()) and ((file_put_contents('titles.txt',serialize($tmp))) !== false) ) ) ) { echo 'Reverting ...'."\n"; $rev = $wpapi->revisions($change['title'],5,'older',false,$change['old_revid']); $revid = 0; foreach ($rev as $revdata) { if ($revdata['user'] != $change['user']) { $revid = $revdata['revid']; break; } } if (($revdata['user'] == $user) or (in_array($revdata['user'],explode(',',$botfriends)))) { die(); /* Do not revert to us. */ } if ($revid == 0) { die(); } foreach (explode(',',$ircdebugchannel) as $y) { fwrite($irc,'PRIVMSG '.$y.' :Reverting ...'."\n"); } $revisiondata = $wpapi->revisions($change['title'],1,'older',true,$revid); if (!$revisiondata[0]['*']) die(); $wpi->post( $change['title'], $revisiondata[0]['*'], 'Reverting possible vandalism by [[Special:Contributions/'.$change['user'].']] ' . 'to version by '.$revisiondata[0]['user'].'. ' . 'False positive? [[User:'.$user.'/FalsePositives|report it]]. '. 'Thanks, [[User:'.$user.'|'.$user.']]. ('.$mysqlid.') (Bot)' ); /* Revert the page */ $rv2 = $wpapi->revisions($change['title'],1); if ($rv2[0]['user'] == $user) { $warning = 0; if (preg_match_all('/<!-- Template:(uw-[a-z]*(\d)(im)?|Blatantvandal \(serious warning\)) -->;.*(\d{2}):(\d{2}), (\d+) ([a-zA-Z]+) (\d{4}) \(UTC\)/iU', $wpq->getpage('User talk:'.$change['user']), $match,PREG_SET_ORDER) ) { foreach ($match as $m) { $month = array('January' => 1, 'February' => 2, 'March' => 3, 'April' => 4, 'May' => 5, 'June' => 6, 'July' => 7, 'August' => 8, 'September' => 9, 'October' => 10, 'November' => 11, 'December' => 12 ); if ($m[1] == 'Blatantvandal (serious warning)') $m[2] = 4; if ((time() - gmmktime($m[4],$m[5],0,$month[$m[7]],$m[6],$m[8])) <= (2*24*60*60)) { if ($m[2] > $warning) { $warning = $m[2]; } } } } $warning++; if ($warning == 5) { /* Report them if they have been warned 4 times. */ $aivdata = $wpq->getpage('Wikipedia:Administrator_intervention_against_vandalism/TB2'); if (!preg_match('/'.preg_quote($change['user'],'/').'/i',$aivdata)) { foreach(explode(',',$ircaivchannel) as $y) { fwrite($irc,'PRIVMSG '.$y.' :!admin Reporting [[User:'.$change['user'].']] to [[WP:AIV]]. Contributions: [[Special:Contributions/'.$change['user'].']] Block: [[Special:Blockip/'.$change['user'].']]'."\n"); } foreach (explode(',',$ircvandalismchannel) as $y) { fwrite($irc,'PRIVMSG '.$y.' :computer bl add '.$change['user'].' x='.(24*$warning).' r=Vandalism to [['.$change['title'].']] (#'.$warning.").\n"); } $wpi->post( 'Wikipedia:Administrator_intervention_against_vandalism/TB2', $aivdata . "\n\n* {{".((long2ip(ip2long($change['user'])) == $change['user'])?'IPvandal':'Vandal').'|'.$change['user'].'}}' . ' - '.$report." (Automated) <font face="Copperplate Gothic">[[User:Gp75motorsports|<font color="#FF0000">Gp</font><font color="#000000">75</font><font color="#FF0000">motorsports</font>]] <sup><font color="#800000">[[User talk:Gp75motorsports|REV LIMITER]]</font></sup></font> 22:39, 2 January 2008 (UTC)\n", 'Automatically reporting [[Special:Contributions/'.$change['user'].']]. (bot)' ); } else { foreach (explode(',',$ircreportchannel) as $y) { fwrite($irc,'PRIVMSG '.$y.' :!admin [[User:'.$change['user'].']] has vandalized at least one time while being listed on [[WP:AIV]]. Contributions: [[Special:Contributions/'.$change['user'].']] Block: [[Special:Blockip/'.$change['user'].']]'."\n"); } } } elseif ($warning < 5) { /* Warn them if they haven't been warned 4 times. */ foreach (explode(',',$ircvandalismchannel) as $y) { fwrite($irc,'PRIVMSG '.$y.' :computer bl add '.$change['user'].' x='.(24*$warning).' r=Vandalism to [['.$change['title'].']] (#'.$warning.').'."\n"); } $wpi->post( 'User talk:'.$change['user'], $wpq->getpage('User talk:'.$change['user'])."\n\n" . '{{subst:User:'.$user.'/Warnings/Warning|1='.$warning.'|2='.$change['title'].'|3='.$report.' <;!-- MySQL ID: '.$mysqlid.' -->;}} <font face="Copperplate Gothic">[[User:Gp75motorsports|<font color="#FF0000">Gp</font><font color="#000000">75</font><font color="#FF0000">motorsports</font>]] <sup><font color="#800000">[[User talk:Gp75motorsports|REV LIMITER]]</font></sup></font> 22:39, 2 January 2008 (UTC)'."\n", 'Warning [[User:'.$change['user'].']] - #'.$warning ); /* Warn the user */ } else { /* They have already been reported ... do nothing */ } if (!mysql_ping($mysql)) { $mysql = mysql_pconnect($mysqlhost.':'.$mysqlport,$mysqluser,$mysqlpass); if (!$mysql) { die('Could not connect: ' . mysql_error()); } if (!mysql_select_db($mysqldb, $mysql)) { die ('Can\'t use database : ' . mysql_error()); } } mysql_query('UPDATE `vandalism` SET `reverted` = 1 WHERE `id` = \''.mysql_real_escape_string($mysqlid).'\''); } else { if ($change['user'] != $rv2[0]['user']) { echo 'Grr! Beaten by '.$rv2[0]['user'].".\n"; foreach(explode(',',$ircdebugchannel) as $y) { fwrite($irc,'PRIVMSG '.$y.' :Grr! Beaten by '.$rv2[0]['user'].".\n"); } if (!mysql_ping($mysql)) { $mysql = mysql_pconnect($mysqlhost.':'.$mysqlport,$mysqluser,$mysqlpass); mysql_select_db($mysqldb, $mysql); } mysql_query('INSERT INTO `beaten` (`id`,`article`,`diff`,`user`) VALUES (NULL,\''.mysql_real_escape_string($change['title']).'\',\''.mysql_real_escape_string($change['url']).'\',\''.mysql_real_escape_string($rv2[0]['user']).'\')'); } } } else { foreach (explode(',',$ircunrevertedchannels) as $y) { fwrite($irc,'PRIVMSG '.$y.' :'."\002\00304Possible ignored vandalism: \002\003[[\00312".$change['title']."\003]]\00304 changed by \003[[\00312User:".$change['user']."\003]] \00303".$reason."\00304 on \00307".$rv[0]['timestamp']."\003(\002\00313".$s."\003).\n"); fwrite($irc,'PRIVMSG '.$y.' :'."\002(\002\00312 http://en.wikipedia.org/w/index.php?title=".urlencode($change['title'])."&;action=history \003\002|\002\00312 ".$change['url']." \003\002)\002"."\n"); } } } else { $rev = $wpapi->revisions($change['title'],1); $rev = $rev[0]; echo 'Possible corrected vandalism: '.$change['title'].' changed by '.$change['user'].' '.$reason.'('.$s.")\n\tReverted by ".$rev['user']." before I saw it.\n"; foreach (explode(',',$ircdebugchannel) as $y) { fwrite($irc,'PRIVMSG '.$y.' :Possible corrected vandalism: '.$change['title'].' changed by '.$change['user'].' '.$reason.'('.$s.")\n"); fwrite($irc,'PRIVMSG '.$y.' :Reverted by '.$rev['user']." before I saw it.\n"); } if (($rev['user'] != $user) and ($rev['user'] != $change['user'])) { if (!mysql_ping($mysql)) { $mysql = mysql_pconnect($mysqlhost.':'.$mysqlport,$mysqluser,$mysqlpass); mysql_select_db($mysqldb, $mysql); } mysql_query('INSERT INTO `beaten` (`id`,`article`,`diff`,`user`) VALUES (NULL,\''.mysql_real_escape_string($change['title']).'\',\''.mysql_real_escape_string($change['url']).'\',\''.mysql_real_escape_string($rev['user']).'\')'); } } } } die(); } } } } ?> [edit] Heuristics [edit] Config (cluebot.heuristics.config.php) <?PHP $heuristics[] = 'pagereplace'; $heuristics[] = 'pageblank'; $heuristics[] = 'massdelete'; $heuristics[] = 'massadd'; $heuristics[] = 'smallchange'; ?> [edit] heuristics/cluebot.massadd.heuristic.php <?PHP if ( /* Massive additions */ ($change['length'] >= 7500) and ($rv = $wpapi->revisions($change['title'],2,'older',true,$change['revid'])) and ($pagedata = $wpq->getpage($change['title'])) and ($s = score($scorelist,diff($rv[1]['*'],$rv[0]['*']))) and ($s += (score($scorelist,diff($rv[1]['*'],$rv[0]['*'],false))) * -1) and ($s < -1000) and ($reason = 'score equals '.$s) ) $heuristicret = true; ?> [edit] heuristics/cluebot.massdelete.heuristic.php <?PHP if ( /* Massive deletes */ ($change['length'] <= -7500) and ($pagedata = $wpq->getpage($change['title'])) and (!fnmatch('*#REDIRECT*',strtoupper(substr($pagedata,0,9)))) and ($rv = $wpapi->revisions($change['title'],2,'older',true,$change['revid'])) and ($s = score($scorelist,diff($rv[1]['*'],$rv[0]['*']))) and ($s += (score($scorelist,diff($rv[1]['*'],$rv[0]['*'],false))) * -1) and ($s < -50) /* There are times when massive deletes are ok. */ and ($reason = 'deleting '.($change['length'] * -1).' characters') ) $heuristicret = true; ?> [edit] heuristics/cluebot.pageblank.heuristic.php <?PHP if ( /* Page blanks */ (preg_match('/\[\[WP:AES.*Blanked.*page/',$change['comment'],$m)) and (($pagedata = $wpq->getpage($change['title'])) or true) and ($fc = $wpapi->revisions($change['title'],1,'newer')) and ($fc[0]['user'] != $change['user']) /* The creator is allowed to blank the page. */ and ($reason = 'blanking the page') ) $heuristicret = true; ?> [edit] heuristics/cluebot.pagereplace.heuristic.php <?PHP if ( /* Page replaces */ (preg_match('/\[\[WP:AES\|.*\]\]Replaced page with (.*)$/',$change['comment'],$m)) and ($pagedata = $wpq->getpage($change['title'])) and ($fc = $wpapi->revisions($change['title'],1,'newer')) and ($fc[0]['user'] != $change['user']) /* The creator is allowed to replace the page. */ and ($reason = 'replacing entire content with something else') ) $heuristicret = true; ?> [edit] heuristics/cluebot.smallchange.heuristic.php <?PHP if ( /* Small changes with obscenities. */ (($change['length'] >= -200) and ($change['length'] <= 200)) and (($rv = $wpapi->revisions($change['title'],2,'older',true,$change['revid'])) or true) and (!fnmatch('*#REDIRECT*',strtoupper(substr($rv[0]['*'],0,9)))) and ((($change['title'] == 'User:ClueBot/Sandbox') and print_r($rv)) or true) and (($d1 = diff($rv[1]['*'],$rv[0]['*'],true,true)) or true) and (($s = score($obscenelist,$d1)) or true) and (($s -= score($obscenelist,diff($rv[1]['*'],$rv[0]['*'],false,true))) or true) // and ((print($change['title'].' Score = '.$s."\n")) or true) and ( ( ($s < -5) /* There are times when small changes are ok. */ and (!fnmatch('*SEX*',strtoupper($rv[1]['*']))) and (!fnmatch('*BDSM*',strtoupper($rv[1]['*']))) and (score($obscenelist,$change['title']) >= 0) and (score($obscenelist,$rv[1]['*']) >= 0) and (!preg_match('/(^|\s)([a-z]{1,2}(\*+|\-{3,})[a-z]{0,2}|\*{4}|\-{4}|(\<|\()?censored(\>|\))?)(ing?|ed)?(\s|$)/i',$rv[1]['*'])) and ($heuristic .= '/obscenities') and ($reason = 'making a minor change with obscenities') ) or ( ($s > 5) and (!preg_match('/(^|\s)([a-z]{1,2}(\*+|\-{3,})[a-z]{0,2}|\*{4}|\-{4}|(\<|\()?censored(\>|\))?)(ing?|ed)?(\s|$)/i',$rv[1]['*'])) and (preg_match('/(^|\s)([a-z]{1,2}(\*+|\-{3,})[a-z]{0,2}|\*{4}|\-{4}|(\<|\()?censored(\>|\))?)(ing?|ed)?(\s|$)/i',$d1)) and ($heuristic .= '/censor') and ($reason = 'making a minor change censoring content ([[WP:CENSOR|Wikipedia is not censored]])') ) or ( (preg_match('/\!\!\!/',$d1)) and (!preg_match('/\!\!\!/',$rv[1]['*'])) and ($heuristic .= '/exclamation') and ($reason = 'making a minor change adding "!!!"') ) ) ) { $heuristicret = true; /* fwrite($irc,'PRIVMSG #wikipedia-BAG/ClueBot :Would revert http://en.wikipedia.org/w/index.php?title='.urlencode($change['namespace'].$change['title']).'&;diff=prev'.'&oldid='.urlencode($change['revid'])." .\n"); */ } ?> [edit] Score list <?PHP /* * This page contains bad words out of necessity. * Here is 50 lines of whitespace before the actual list: * (scroll down to see the list) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Here is the list: */ $obscenelist = Array ( /* 'preg' => points, */ '/suck/i' => -5, /* Usually bad words */ '/stupid/i' => -3, '/haha/i' => -5, '/\bomg/i' => -3, '/\bpimp\b/i' => -7, '/1337/i' => -5, '/leet/i' => -5, '/dumb/i' => -5, '/\bputa\b/i' => -7, '/\bhomo\b/i' => -7, '/\bGAY\b/' => -10, '/\bslut/i' => -5, '/damn/i' => -5, '/\bass\b/i' => -10, '/\brape\b/i' => -7, '/\bpoop\b/i' => -10, '/\bcock\b/i' => -10, '/\blol\b/i' => -7, '/\bcrap\b/i' => -5, '/\bsex\b/i' => -5, '/noob/i' => -5, '/\bnazi\b/i' => -3, '/\bneo-nazi\b/i' => +3, /* False-positive */ '/fuck/i' => -20, /* Stronger bad words */ '/\[\[Fucked\ Up\]\]/' => +20, /* This one is a false positive */ '/bitch/i' => -20, '/\bpussy\b/i' => -20, '/penis/i' => -20, '/vagina/i' => -20, '/whore/i' => -15, '/\bshit\b/i' => -20, '/nigger/i' => -20, '/\bnigga\b/i' => -20, '/cocksucker/i' => -20, '/assrape/i' => -15, '/motherfucker/i' => -20, '/wanker/i' => -20, '/\bcunt\b/i' => -20, '/faggot/i' => -20, '/fags/i' => -20, '/asshole/i' => -15, '/fuck ((yo)?u|h(er|im)|them|it)/i' => -100, /* This looks like a personal attack */ '/((yo)?u|s?he|we|they|it) sucks?/i' => -100, /* This looks like a personal attack */ '/666+\b/i' => -50 /* Though this has uses, it is commonly used by vandals */ ); $grammarlist = Array ( '/(.{1,4})\1{30}/' => -10, /* Ugg .. the same letter(s) several times in a row. */ '/\b[A-Z].*[.!?]\b/U' => +2, /* This looks to be a correct sentence */ '/\b[A-Z][^a-z]{30,}\b/U' => -10, /* All capitals? Looks like vandal activity */ '/\b[^A-Z]{1500,}\b/U' => -10, /* No capitals? Looks like vandal activity */ '/!{5,}/i' => -10, /* No wikipedia article needs '!!!!!' in it */ '/!!+1+(one)*/i' => -30, /* No wikipedia article needs '!!!11one' in it */ '/\[\[.*\]\]/U' => +1, /* Wiki links are good. */ '/\{\{.*\}\}/U' => +5, /* Wiki transcludes are good. */ '/\{\{[iI]nfobox .*\}\}/U' => +20, /* Wiki infoboxes are good. */ '/\[\[Category\:.*\]\]/iU' => +3 /* Wiki categories are good. */ ); $scorelist = array_merge($obscenelist,$grammarlist); ?>