Sandbox

From MyLunia Wiki

Jump to: navigation, search

Contents

[edit] Classes (wikibot.classes.php)

<?PHP
	class http {
		private $ch;
		private $uid;
		public $postfollowredirs;
		public $getfollowredirs;

		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);
			$this->postfollowredirs = 0;
			$this->getfollowredirs = 1;
		}

		function post ($url,$data) {
//			echo 'POST: '.$url."\n";
			$time = microtime(1);
			curl_setopt($this->ch,CURLOPT_URL,$url);
			curl_setopt($this->ch,CURLOPT_FOLLOWLOCATION,$this->postfollowredirs);
			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) );
			curl_setopt($this->ch,CURLOPT_POSTFIELDS, $data);
			$data = curl_exec($this->ch);
			//var_dump($data);
			echo 'POST: '.$url.' ('.(microtime(1) - $time).' s) ('.strlen($data)." b)\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,$this->getfollowredirs);
			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);
			//var_dump($data);
			echo 'GET: '.$url.' ('.(microtime(1) - $time).' s) ('.strlen($data)." b)\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 getedittoken () {
			$x = $this->http->get($this->apiurl.'?action=query&format=php&prop=info&intoken=edit&titles=Main%20Page');
			$x = unserialize($x);
			foreach ($x['query']['pages'] as $y) {
				return $y['edittoken'];
			}
		}

		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 search ($search,$limit = 10,$offset = 0,$namespace = 0,$what = 'text',$redirs = false) {
			$append = '';
			if ($limit != null) $append .= '&srlimit='.urlencode($limit);
			if ($offset != null) $append .= '&sroffset='.urlencode($offset);
			if ($namespace != null) $append .= '&srnamespace='.urlencode($namespace);
			if ($what != null) $append .= '&srwhat='.urlencode($what);
			if ($redirs == true) $append .= '&srredirects=1';
			else $append .= '&srredirects=0';
			$x = $this->http->get($this->apiurl.'?action=query&list=search&format=php&srsearch='.urlencode($search).$append);
			$x = unserialize($x);
			return $x['query']['search'];
		}

		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);
			$continue = $x['query-continue']['usercontribs']['ucstart'];
			return $x['query']['usercontribs'];
		}

		function revisions ($page,$count = 1,$dir = 'older',$content = false,$revid = null,$wait = true,$getrbtok = false,$dieonerror = true,$redirects = false) {
			$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&meta=userinfo&rvdir='.urlencode($dir).(($revid !== null)?'&rvstartid='.urlencode($revid):'').(($getrbtok == true)?'&rvtoken=rollback':'').(($redirects == true)?'&redirects':''));
			$x = unserialize($x);
			if ($revid !== null) {
				$found = false;
				if (!isset($x['query']['pages']) or !is_array($x['query']['pages'])) {
					if ($dieonerror == true) die('No such page.'."\n");
					else return false;
				}
				foreach ($x['query']['pages'] as $data) {
					if (!isset($data['revisions']) or !is_array($data['revisions'])) {
						if ($dieonerror == true) die('No such page.'."\n");
						else return false;
					}
					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,$getrbtok,$dieonerror);
					} else {
						if ($dieonerror == true) die('Revision error.'."\n");
					}
				}
			}
			foreach ($x['query']['pages'] as $data) {
				$data['revisions']['ns'] = $data['ns'];
				$data['revisions']['title'] = $data['title'];
				$data['revisions']['currentuser'] = $x['query']['userinfo']['name'];
//				$data['revisions']['currentuser'] = $x['query']['userinfo']['currentuser']['name'];
				$data['revisions']['continue'] = $x['query-continue']['revisions']['rvstartid'];
				return $data['revisions'];
			}
		}

		function users ($start = null,$limit = 1,$group = null,$reqirestart = false,&$continue = null) {
			$append = '';
			if ($start != null) $append .= '&aufrom='.urlencode($start);
			if ($group != null) $append .= '&augroup='.urlencode($group);
			$x = $this->http->get($this->apiurl.'?action=query&list=allusers&format=php&auprop=editcount|registration|groups&aulimit='.urlencode($limit).$append);
			$x = unserialize($x);
			$continue = $x['query-continue']['allusers']['aufrom'];
			if (($requirestart == true) and ($x['query']['allusers'][0]['name'] != $start)) return false;
			return $x['query']['allusers'];
		}


		function categorymembers ($category,$count = 500,&$continue = null) {
			if ($continue != null) {
				$append = '&cmcontinue='.urlencode($continue);
			} else {
				$append = '';
			}
			$category = 'Category:'.str_ireplace('category:','',$category);
			$x = $this->http->get($this->apiurl.'?action=query&list=categorymembers&cmtitle='.urlencode($category).'&format=php&cmlimit='.$count.$append);
			$x = unserialize($x);
			$continue = $x['query-continue']['categorymembers']['cmcontinue'];
			return $x['query']['categorymembers'];
		}

		function listcategories (&$start = null,$limit = 50,$dir = 'ascending',$prefix = null) {
			$append = '';
			if ($start != null) $append .= '&acfrom='.urlencode($start);
			if ($limit != null) $append .= '&aclimit='.urlencode($limit);
			if ($dir != null) $append .= '&acdir='.urlencode($dir);
			if ($prefix != null) $append .= '&acprefix='.urlencode($prefix);

			$x = $this->http->get($this->apiurl.'?action=query&list=allcategories&acprop=size&format=php'.$append);
			$x = unserialize($x);

			$start = $x['query-continue']['allcategories']['acfrom'];

			return $x['query']['allcategories'];
		}

		function backlinks ($page,$count = 500,&$continue = null,$filter = null) {
			if ($continue != null) {
				$append = '&blcontinue='.urlencode($continue);
			} else {
				$append = '';
			}
			if ($filter != null) {
				$append .= '&blfilterredir='.urlencode($filter);
			}

			$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;
		private $edittoken;

		function __construct () {
			global $__wp__http;
			if (!isset($__wp__http)) {
				$__wp__http = new http;
			}
			$this->http = &$__wp__http;
		}

		function post ($page,$data,$summery = '',$minor = false,$rv = null,$bot = true) {
			global $user;
			global $maxlag;
			global $irc;
			global $irctechchannel;
			global $run;
			global $maxlagkeepgoing;

			$wpq = new wikipediaquery; $wpq->queryurl = str_replace('index.php','query.php',$this->indexurl);
			$wpapi = new wikipediaapi; $wpapi->apiurl = str_replace('index.php','api.php',$this->indexurl);

			if ((!$this->edittoken) or ($this->edittoken == '')) $this->edittoken = $wpapi->getedittoken();
			if ($rv == null) $rv = $wpapi->revisions($page,1,'older',true);
			if (!$rv[0]['*']) $rv[0]['*'] = $wpq->getpage($page);

			//Fake the edit form.
			$now = gmdate('YmdHis', time());
			$token = htmlspecialchars($this->edittoken);
			$tmp = date_parse($rv[0]['timestamp']);
			$edittime = gmdate('YmdHis', gmmktime($tmp['hour'],$tmp['minute'],$tmp['second'],$tmp['month'],$tmp['day'],$tmp['year']));
			$html = "<input type='hidden' value=\"{$now}\" name=\"wpStarttime\" />\n";
			$html.= "<input type='hidden' value=\"{$edittime}\" name=\"wpEdittime\" />\n";
			$html.= "<input type='hidden' value=\"{$token}\" name=\"wpEditToken\" />\n";
			$html.= '<input name="wpAutoSummary" type="hidden" value="'.md5('').'" />'."\n";

			if (preg_match('/'.preg_quote('{{nobots}}','/').'/iS',$rv[0]['*'])) { return false; }		/* Honor the bots flags */
			if (preg_match('/'.preg_quote('{{bots|allow=none}}','/').'/iS',$rv[0]['*'])) { return false; }
			if (preg_match('/'.preg_quote('{{bots|deny=all}}','/').'/iS',$rv[0]['*'])) { return false; }
			if (preg_match('/'.preg_quote('{{bots|deny=','/').'(.*)'.preg_quote('}}','/').'/iS',$rv[0]['*'],$m)) { if (in_array(explode(',',$m[1]),$user)) { return false; } } /* /Honor the bots flags */
			if (!preg_match('/'.preg_quote($user,'/').'/iS',$rv['currentuser'])) { return false; } /* We need to be logged in */
//			if (preg_match('/'.preg_quote('You have new messages','/').'/iS',$rv[0]['*'])) { return false; } /* Check talk page */
			if (!preg_match('/(yes|enable|true)/iS',((isset($run))?$run:$wpq->getpage('User:'.$user.'/Run')))) { return false; } /* Check /Run page */

			$x = $this->forcepost($page,$data,$summery,$minor,$html,$maxlag,$maxlagkeepgoing,$bot); /* Go ahead and post. */
			$this->lastpost = time();
			return $x;
		}

		function forcepost ($page,$data,$summery = '',$minor = false,$edithtml = null,$maxlag = null,$mlkg = null,$bot = true) {
			$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];
			if ($maxlag != null) {
				$x = $this->http->post($this->indexurl.'?title='.urlencode($page).'&action=submit&maxlag='.urlencode($maxlag).'&bot='.(($bot == true)?'1':'0'),$post);
				if (preg_match('/Waiting for ([^ ]*): ([0-9.-]+) seconds lagged/S',$x,$lagged)) {
					global $irc;
					if (is_resource($irc)) {
						global $irctechchannel;
						foreach(explode(',',$irctechchannel) as $y) {
							fwrite($irc,'PRIVMSG '.$y.' :'.$lagged[1].' is lagged out by '.$lagged[2].' seconds. ('.$lagged[0].')'."\n");
						}
					}
					sleep(10);
					if ($mlkg != true) { return false; }
					else { $x = $this->http->post($this->indexurl.'?title='.urlencode($page).'&action=submit&bot='.(($bot == true)?'1':'0'),$post); }
				}
				return $x;
			} else {
				return $this->http->post($this->indexurl.'?title='.urlencode($page).'&action=submit&bot='.(($bot == true)?'1':'0'),$post);
			}
		}

		function diff ($title,$oldid,$id,$wait = true) {
			$deleted = '';
			$added = '';

			$html = $this->http->get($this->indexurl.'?title='.urlencode($title).'&action=render&diff='.urlencode($id).'&oldid='.urlencode($oldid).'&diffonly=1');

			if (preg_match_all('/\&amp\;(oldid\=|undo=)(\d*)\\\'\>(Revision as of|undo)/USs', $html, $m, PREG_SET_ORDER)) {
				//print_r($m);
				if ((($oldid != $m[0][2]) and (is_numeric($oldid))) or (($id != $m[1][2]) and (is_numeric($id)))) {
					if ($wait == true) {
						sleep(1);
						return $this->diff($title,$oldid,$id,false);
					} else {
						die('Revision error.'."\n");
					}
				}
			}
			
			if (preg_match_all('/\<td class\=(\"|\\\')diff-addedline\1\>\<div\>(.*)\<\/div\>\<\/td\>/USs', $html, $m, PREG_SET_ORDER)) {
				//print_r($m);
				foreach ($m as $x) {
					$added .= htmlspecialchars_decode(strip_tags($x[2]))."\n";
				}
			}

			if (preg_match_all('/\<td class\=(\"|\\\')diff-deletedline\1\>\<div\>(.*)\<\/div\>\<\/td\>/USs', $html, $m, PREG_SET_ORDER)) {
				//print_r($m);
				foreach ($m as $x) {
					$deleted .= htmlspecialchars_decode(strip_tags($x[2]))."\n";
				}
			}

			//echo $added."\n".$deleted."\n";

			if (preg_match('/action\=rollback\&amp\;from\=.*\&amp\;token\=(.*)\"/US', $html, $m)) {
				$rbtoken = urldecode($rbtoken);
				return array($added,$deleted,$rbtoken);
			}

			return array($added,$deleted);
		}

		function rollback ($title,$user,$reason = null,$token = null,$bot = true) {
			if (($token == null) or (!$token)) {
				$wpapi = new wikipediaapi; $wpapi->apiurl = str_replace('index.php','api.php',$this->indexurl);
				$token = $wpapi->revisions
($title,1,'older',false,null,true,true);
				if ($token[0]['user'] == $user) {
					$token = $token[0]['rollbacktoken'];
				} else {
					return false;
				}
			}
			$x = $this->http->get($this->indexurl.'?title='.urlencode($title).'&action=rollback&from='.urlencode($user).'&token='.urlencode($token).(($reason != null)?'&summary='.urlencode($reason):'').'&bot='.(($bot == true)?'1':'0'));
			if (!preg_match('/action complete/iS',$x)) return false;
			return $x;
		}

		function move ($old,$new,$reason) {
			$wpapi = new wikipediaapi; $wpapi->apiurl = str_replace('index.php','api.php',$this->indexurl);
			if ((!$this->edittoken) or ($this->edittoken == '')) $this->edittoken = $wpapi->getedittoken();

			$token = htmlspecialchars($this->edittoken);

			$post = array
				(
					'wpOldTitle'	=> $old,
					'wpNewTitle'	=> $new,
					'wpReason'	=> $reason,
					'wpWatch'	=> '0',
					'wpEditToken'	=> $token,
					'wpMove'	=> 'Move page'
				);
			return $this->http->post($this->indexurl.'?title=Special:Movepage&action=submit',$post);
		}

		function upload ($page,$file,$desc) {
			$post = array
				(
					'wpUploadFile'		=> '@'.$file,
					'wpSourceType'		=> 'file',
					'wpDestFile'		=> $page,
					'wpUploadDescription'	=> $desc,
					'wpLicense'		=> '',
					'wpWatchthis'		=> '0',
					'wpIgnoreWarning'	=> '1',
					'wpUpload'		=> 'Upload file'
				);
			return $this->http->post($this->indexurl.'?title=Special:Upload&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,&$matches = null) {
		$ret = 0;
		foreach ($list as $preg => $pts) {
			if ($x = preg_match_all($preg.'S',$data,$m)) {
//				echo $x.'*'.$pts.' ('.$preg.')'."\n";
				$matches[$preg] = $x;
				$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].' ~~~~'."\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~~~~",
		'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)) {
			$rawline = fgets($feed,1024);
			$line = str_replace(array("\n","\r","\002"),'',$rawline);
			$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+)? \* ([^*]*) \* (\(([^)]*)\))? (.*)$/S',$message,$m)) {
					$messagereceived = microtime(1);
					$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]++;
							print_r($log);
							file_put_contents('cluebot.heuristics.stats.txt',serialize($stats));
							unset($stats);
							break;
						}
					}

					if ($heuristicret == true) { echo 'Heuristics time: '.(microtime(1) - $hutime)."\n"; file_put_contents('trainingdata.txt',$change['title']."\0".$change['revid']."\0".'1'."\n",FILE_APPEND); }
					else {
						$tmp = explode(' ',$rawline,4); $tmp = $tmp[3];
						$udp = fsockopen('udp://localhost',3333);
						fwrite($udp,substr(str_replace(array("\n","\r"),'',$tmp),1)."\n");
						fclose($udp);
						unset($tmp,$udp);
						$d = $wpi->diff($change['title'],$change['old_revid'],$change['revid']);
						$s = score($obscenelist,$d[0],$log);
						$s -= score($obscenelist,$d[1],$log);
						if ($s > 15) file_put_contents('trainingdata.txt',$change['title']."\0".$change['revid']."\0".'0'."\n",FILE_APPEND);
					}
					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 ' .
								'[[Special:Contributions/'.$change['user'].'|'.$change['user'].']] ' .
								'[[User:'.$change['user'].'|(u)]] ' .
								'[[User talk:'.$change['user'].'|(t)]] ' .
								$reason.' on '.gmdate('c');
//							$datatopost = $vandalpage."\n\n".'Possible [[WP:VAN|vandalism]]: '.$report." ~~~~\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 (
								($rv1 = $wpapi->revisions($change['title'],1,'older'))
								and ($rv1[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);

								if (is_array($log)) {
									$logt = '';
									foreach ($log as $k => $v) {
										$logt .= '* '.$v.' * "'.$k.'"'."\n";
									}
								}

								$query = 'INSERT INTO `vandalism` ' .
									'(`id`,`user`,`article`,`heuristic`'.((is_array($log))?',`regex`':'').',`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).'\',' .
									((is_array($log))?'\''.mysql_real_escape_string($logt).'\',':'') .
									'\''.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)/iS',$status))
											and (print('Revert [y/N]? '))
											and (strtolower(substr(fgets($stdin,3),0,1)) == 'y')
										)
										or (
											(preg_match('/(read-write|rw|go|approved|trial)/iS',$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 'Reverted ...'."\n";
									$rev = $wpapi->revisions($change['title'],5,'older',false,null,true,true);
									$revid = 0;
									$rbtok = $rev[0]['rollbacktoken'];
									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();
//									if (!$rv1[0]['*']) $rv1
[0]['*'] = $rv[0]['*'];
//									$wpi->post(
//										$change['title'],
//										$revisiondata[0]['*'],
//										'Reverted possible vandalism by [[Special:Contributions/'.$change['user'].'|'.$change['user'].']] ' .
//										'to version by '.$revisiondata[0]['user'].'. ' .
//										'False positive? [[User:'.$user.'/FalsePositives|Report it]]. '.
//										'Thanks, [[User:'.$user.'|]]. ('.$mysqlid.') (Bot)',
//										false,
//										$rv1
//									); /* Revert the page */
									$rbret = $wpi->rollback(
										$change['title'],
										$change['user'],
										'Reverted possible vandalism by [[Special:Contributions/'.$change['user'].'|'.$change['user'].']] ' .
										'to '.(($revid == 0)?'older version':'version by '.$revdata['user']).'. ' .
										'False positive? [[User:'.$user.'/FalsePositives|Report it]]. '.
										'Thanks, [[User:'.$user.']]. ('.$mysqlid.') (Bot)',
										$rbtok,
										false
									);
//
// 									$rv2 = $wpapi->revisions($change['title'],1);
//									if ($rv2[0]['user'] == $user) {
									if ($rbret !== false) {
										foreach (explode(',',$ircdebugchannel) as $y) {
											fwrite($irc,'PRIVMSG '.$y.' :Reverted. ('.(microtime(1) - $messagereceived).' s)'."\n");
										}
 										$warning = 0;
										$tpcontent = $wpq->getpage('User talk:'.$change['user']);
										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',
											$tpcontent,
											$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) ~~~~\n",
													'Automatically reporting [[Special:Contributions/'.$change['user'].']]. (bot)',
													false,
													null,
													false
												);
											} 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'],
												$tpcontent."\n\n" .
												'{{subst:User:'.$user.'/Warnings/Warning|1='.$warning.'|2='.$change['title'].'|3='.$report.' <!{{subst:ns:0}}-- MySQL ID: '.$mysqlid.' --{{subst:ns:0}}>}} ~~~~'."\n",
												'Warning [[Special:Contributions/'.$change['user'].'|'.$change['user'].']] - #'.$warning,
												false,
												null,
												false
											); /* 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 {
										$rv2 = $wpapi->revisions($change['title'],1);
										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[] = 'evolution';
	$heuristics[] = 'pagereplace';
	$heuristics[] = 'pageblank';
	$heuristics[] = 'massdelete';
	$heuristics[] = 'massadd';
	$heuristics[] = 'smallchange';
?>

[edit] heuristics/cluebot.evolution.heuristic.php

<?PHP
	if ( /* The Evolution vandal */
		($change['title'] == 'Evolution')
		and (($pagedata = $wpq->getpage($change['title'])) or true)
		and (fnmatch('*Genesis 1*The beginning*',$pagedata))
		and ($reason = 'replacing article with the Bible')
	) {
		$heuristicret = true;
		fwrite($irc,'PRIVMSG #cvn-wp-en :!admin Evolution vandal? http://en.wikipedia.org/w/index.php?title='.urlencode($change['title']).'&diff=prev'.'&oldid='.urlencode($change['revid'])." .\n");
	}
?>

[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,$rv[0]['*']))
		and ($s += (score($scorelist,$rv[1]['*'])) * -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,$rv[0]['*']))
		and ($s += (score($scorelist,$rv[1]['*'])) * -1)
		and ($s < -50) /* There are times when massive deletes are ok. */
		and ($reason = 'deleting '.($change['length'] * -1).' characters')
	) $heuristicret = true;
?>

[edit] heuristics/cluebot.pagereplace.heuristic.php

<?PHP
	if ( /* Page replaces */
		(preg_match('/\[\[WP:.*\]\]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
	unset($log,$log2);
	if ( /* Small changes with obscenities. */
		(($change['length'] >= -200) and ($change['length'] <= 200))
		and (($d = $wpi->diff($change['title'],$change['old_revid'],$change['revid'])) or true)
		and ((($change['title'] == 'User:ClueBot/Sandbox') and print_r($rv)) or true)
		and (($s = score($obscenelist,$d[0],$log)) or true)
		and (($s -= score($obscenelist,$d[1],$log2)) or true)
		and (
			(
				($s < -5) /* There are times when small changes are ok. */
				and (($rv = $wpapi->revisions($change['title'],2,'older',true,$change['revid'])) or true)
				and (!fnmatch('*#REDIRECT*',strtoupper(substr($rv[0]['*'],0,9))))
				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|$)/iS',$rv[1]['*']))
				and ($heuristic .= '/obscenities')
				and ($reason = 'making a minor change with obscenities')
			)
			or (
				($s > 5)
				and (($rv = $wpapi->revisions($change['title'],2,'older',true,$change['revid'])) or true)
				and (!fnmatch('*#REDIRECT*',strtoupper(substr($rv[0]['*'],0,9))))
				and (!preg_match('/(^|\s)([a-z]{1,2}(\*+|\-{3,})[a-z]{0,2}|\*{4}|\-{4}|(\<|\()?censored(\>|\))?)(ing?|ed)?(\s|$)/iS',$rv[1]['*']))
				and (preg_match('/(^|\s)([a-z]{1,2}(\*+|\-{3,})[a-z]{0,2}|\*{4}|\-{4}|(\<|\()?censored(\>|\))?)(ing?|ed)?(\s|$)/iS',$rv[0]['*']))
				and ($heuristic .= '/censor')
				and ($reason = 'making a minor change censoring content ([[WP:CENSOR|Wikipedia is not censored]])')
			)
			or (
				(preg_match('/\!\!\!/S',$d[0]))
				and (($rv = $wpapi->revisions($change['title'],2,'older',true,$change['revid'])) or true)
				and (!preg_match('/\!\!\!/S',$rv[1]['*']))
				and (!fnmatch('*#REDIRECT*',strtoupper(substr($rv[0]['*'],0,9))))
				and ($heuristic .= '/exclamation')
				and ($reason = 'making a minor change adding "!!!"')
			)
		)
	) { $heuristicret = true; if (isset($log2) and is_array($log2)) foreach ($log2 as $k => $v) $log[$k] -= $v; if (isset($log) and is_array($log)) foreach ($log as $k => $v) if ($v == 0) unset($log[$k]); unset($log2); /* 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);
?>


ClueBot (talk) 19:19, 22 May 2008 (UTC)

Personal tools