<?php
/* antivandalbot.php - a basic php bot to help controll vandals on media wiki wiki's
Copyright (C) 2008 Chris Grant - http://en.wikipedia.org/wiki/User:Chris_G
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Developers (add your self here if you worked on the code):
Cobi - [[User:Cobi]] - Wrote wikibot.classes.php and some of the code used
Chris - [[User:Chris_G]] - Wrote up the rest of the code
*/
include("wikibot.classes.php"); //Use Cobi's classes - see [[User:Cobi]] and [[User:ClueBot/Source]]
include("ircbot.php"); //My Irc bot framework
include("nickpass.php"); //Contains Nicksev Pass
include("badwords.php"); //The bad words list
//Framework Config
$config = array(
'server' => 'irc.freenode.net',
'port' => 6667,
'nick' => 'AntiVandalBot',
'name' => 'AntiVandalBot',
);
$irc = new IRCBot($config);
$irc->login($config);
$irc->msg('NickServ', "identify $nickpass");
$irc->join_channel('##Chris_G');
//Setup the classes
$h = new http;
$wpapi = new wikipediaapi;
$wpq = new wikipediaquery;
$wpi = new wikipediaindex;
//Setup the url's
$url = 'http://simple.wikipedia.org/w/';
$wpi->indexurl = $url.'index.php';
$wpapi->apiurl = $url.'api.php';
$wpq->queryurl = $url.'query.php';
//All the login stuff
$user = 'Chris_G_Bot';
include('password.php');
$wpapi->login($user,$pass);
//Watch the rc feed
while (1) {
$feedhost = 'irc.wikimedia.org';
$feedport = 6667;
$feedchannel = '#simple.wikipedia';
$feed = fsockopen($feedhost,$feedport);
if (!$feed) {
sleep(10);
$feed = fsockopen($feedhost,$feedport);
if (!$feed) die($feederrstr.' ('.$feederrno.')');
}
fwrite($feed,'USER '.$user.' "1" "1" :ClueBot Wikipedia Bot.'."\n");
fwrite($feed,'NICK '.$user."\n");
while (true) {
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:\/\/simple\.wikipedia\.org\/w\/index\.php\?title=[^&]*&diff=(\d*)&oldid=(\d*)|http:\/\/en\.wikipedia\.org\/wiki\/\S+)? \* ([^*]*) \* (\(([^)]*)\))? (.*)$/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];
echo $change['namespace']." ".$change['title']." ".$change['revid']." ".$change['old_revid']."\n";
$count = $wpq->contribcount($change['user']);
if ($count < 50 and $change['namespace'] == '' or $count < 50 and $change['namespace'] == 'User:' and $change['user'] != $change['title']) {
$change['title'] = $change['namespace'].$change['title'];
$old = $wpq->getpage($change['title'],$change['old_revid']);
$new = $wpq->getpage($change['title'],$change['revid']);
$score = score($obscenelist,$old,$new);
$msg = 'Edit on: [['.$change['title'].']] changed by '.$change['user'].' score '.$score;
$irc->msg('##Chris_G', $msg);
if ($score >= 5) {
$return = revert($change['user'],$change['title']);
if ($return) {
warn($change['user'],$change['title']);
}
$msg = 'Chris_G: Possible vandalism: [['.$change['title'].']] changed by '.$change['user'].' score '.$score.".";
$irc->msg('##Chris_G', $msg);
echo "$msg\n";
}
}
}
}
}
usleep(500);
}
}
function revert($user,$page) {
global $wpapi, $wpq, $wpi;
$x = file_get_contents($wpapi->apiurl.'?action=query&prop=revisions&titles='.urlencode($page).'&rvlimit=500&rvprop=user|ids&format=php');
$hist = unserialize($x);
foreach ($hist['query']['pages'][$wpq->getpageid($page)]['revisions'] as $x) {
if ($user != $x['user']) {
$id = $x['revid'];
$olduser = $x['user'];
break;
}
}
$content = $wpq->getpage($page,$id);
if ($content == $wpq->getpage($page)) {
return false;
}
$summary = "Reverting possible vandalism by [[Special:Contributions/$user|$user]] to last version by $olduser (BOT)";
$wpi->forcepost($page,$content,$summary,'user',false,null,null,null,false);
return true;
}
function warn($user,$title) {
global $h, $wpapi, $wpq, $wpi;
$warning = 0;
$tpcontent = $wpq->getpage('User talk:'.$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) {
echo $m[1];
$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 > 4) {
//report to aiv
$page = "Wikipedia:Vandalism in progress/Bot";
$content = $wpq->getpage($page);
if (preg_match('/^[0-9.]+$/',$user)) {
if (!preg_match("/\{\{ipvandal\|$user\}\}/i",$content)) {
$data = "{{ipvandal|$user}} has been vandalising [[$title]] --~~~~\n".$content;
}
}
else {
if (!preg_match("/\{\{vandal\|$user\}\}/i",$content)) {
$data = "{{vandal|$user}} has been vandalising [[$title]] --~~~~\n".$content;
}
}
if ($data != $content) {
$summary = "Reporting [[Special:Contributions/$user|$user]] (BOT)";
$wpi->forcepost($page,$data,$summary);
}
}
else {
if (empty($tpcontent)) {
$data = "{{subst:User:Chris G/Uw-vandalism{$warning}|$title}} --~~~~";
}
else {
$data = $tpcontent . "\n\n{{subst:User:Chris G/Uw-vandalism{$warning}|$title}} --~~~~";
}
$summary = "Adding level $warning warning about possible vandalism on [[$title]] (BOT)";
$wpi->forcepost('User talk:'.$user,$data,$summary);
}
}
function score ($list,$old,$new) {
$ret = 0;
foreach ($list as $reg => $score) {
if (preg_match($reg,$new) and !preg_match($reg,$old)) {
$ret += $score;
}
}
return $ret;
}
?>