public static function processEditThread($change) { $change['edit_status'] = 'not_reverted'; if (!isset($s)) { $change['edit_score'] = 'N/A'; $s = null; } else { $change['edit_score'] = $s; } if (!in_array('all', $change) || !isVandalism($change['all'], $s)) { Feed::bail($change, 'Below threshold', $s); return; } echo 'Is ' . $change['user'] . ' whitelisted ?' . "\n"; if (Action::isWhitelisted($change['user'])) { Feed::bail($change, 'Whitelisted', $s); return; } echo 'No.' . "\n"; $reason = 'ANN scored at ' . $s; $heuristic = ''; $log = null; $diff = 'https://en.wikipedia.org/w/index.php' . '?title=' . urlencode($change['title']) . '&diff=' . urlencode($change['revid']) . '&oldid=' . urlencode($change['old_revid']); $report = '[[' . str_replace('File:', ':File:', $change['title']) . ']] was ' . '[' . $diff . ' changed] by ' . '[[Special:Contributions/' . $change['user'] . '|' . $change['user'] . ']] ' . '[[User:'******'user'] . '|(u)]] ' . '[[User talk:' . $change['user'] . '|(t)]] ' . $reason . ' on ' . gmdate('c'); $oftVand = unserialize(file_get_contents('oftenvandalized.txt')); if (rand(1, 50) == 2) { foreach ($oftVand as $art => $artVands) { foreach ($artVands as $key => $time) { if (time() - $time > 2 * 24 * 60 * 60) { unset($oftVand[$art][$key]); } } } } $oftVand[$change['title']][] = time(); if (count($oftVand[$change['title']]) >= 30) { IRC::say('reportchannel', '!admin [[' . $change['title'] . ']] has been vandalized ' . count($oftVand[$change['title']]) . ' times in the last 2 days.'); } file_put_contents('oftenvandalized.txt', serialize($oftVand)); $ircreport = "15[[07" . $change['title'] . "15]] by \"03" . $change['user'] . "15\" (12 " . $change['url'] . " 15) 06" . $s . "15 ("; $change['mysqlid'] = Db::detectedVandalism($change['user'], $change['title'], $heuristic, $reason, $change['url'], $change['old_revid'], $change['revid']); echo 'Should revert?' . "\n"; list($shouldRevert, $revertReason) = Action::shouldRevert($change); $change['revert_reason'] = $revertReason; if ($shouldRevert) { echo 'Yes.' . "\n"; $rbret = Action::doRevert($change); if ($rbret !== false) { $change['edit_status'] = 'reverted'; RedisProxy::send($change); IRC::say('debugchannel', $ircreport . "04Reverted15) (13" . $revertReason . "15) (02" . (microtime(true) - $change['startTime']) . " 15s)"); Action::doWarn($change, $report); Db::vandalismReverted($change['mysqlid']); Feed::bail($change, $revertReason, $s, true); } else { $change['edit_status'] = 'beaten'; $rv2 = Api::$a->revisions($change['title'], 1); if ($change['user'] != $rv2[0]['user']) { RedisProxy::send($change); IRC::say('debugchannel', $ircreport . "03Not Reverted15) (13Beaten by " . $rv2[0]['user'] . "15) (02" . (microtime(true) - $change['startTime']) . " 15s)"); Db::vandalismRevertBeaten($change['mysqlid'], $change['title'], $rv2[0]['user'], $change['url']); Feed::bail($change, 'Beaten by ' . $rv2[0]['user'], $s); } } } else { RedisProxy::send($change); IRC::say('debugchannel', $ircreport . "03Not Reverted15) (13" . $revertReason . "15) (02" . (microtime(true) - $change['startTime']) . " 15s)"); Feed::bail($change, $revertReason, $s); } }
public static function shouldRevert($change) { $reason = 'Default revert'; if (preg_match('/(assisted|manual)/iS', Config::$status)) { echo 'Revert [y/N]? '; if (strtolower(substr(fgets(Globals::$stdin, 3), 0, 1)) != 'y') { return array(false, 'Manual mode says no'); } } if (!preg_match('/(yes|enable|true)/iS', Globals::$run)) { return array(false, 'Run disabled'); } if ($change['user'] == Config::$user) { return array(false, 'User is myself'); } if (Config::$angry) { return array(true, 'Angry-reverting in angry mode'); } if (time() - Globals::$tfas >= 1800) { if (preg_match('/\\(\'\'\'\\[\\[([^|]*)\\|more...\\]\\]\'\'\'\\)/iU', Api::$q->getpage('Wikipedia:Today\'s featured article/' . date('F j, Y')), $tfam)) { Globals::$tfas = time(); Globals::$tfa = $tfam[1]; } } if (!self::findAndParseBots($change)) { return array(false, 'Exclusion compliance'); } if ($change['all']['user'] == $change['all']['common']['creator']) { return array(false, 'User is creator'); } if ($change['all']['user_edit_count'] > 50) { if ($change['all']['user_warns'] / $change['all']['user_edit_count'] < 0.1) { return array(false, 'User has edit count'); } else { $reason = 'User has edit count, but warns > 10%'; } } if (Globals::$tfa == $change['title']) { return array(true, 'Angry-reverting on TFA'); } if (preg_match('/\\* \\[\\[(' . preg_quote($change['title'], '/') . ')\\]\\] \\- .*/i', Globals::$aoptin)) { IRC::say('debugchannel', 'Angry-reverting [[' . $change['title'] . ']].'); return array(true, 'Angry-reverting on angry-optin'); } $titles = unserialize(file_get_contents('titles.txt')); if (!isset($titles[$change['title'] . $change['user']]) or time() - $titles[$change['title'] . $change['user']] > 24 * 60 * 60) { $titles[$change['title'] . $change['user']] = time(); file_put_contents('titles.txt', serialize($titles)); return array(true, $reason); } return array(false, 'Reverted before'); }
private static function loop($line) { $d = IRC::split($line); if ($d === null) { return; } if ($d['type'] == 'direct') { switch ($d['command']) { case 'ping': self::send('PONG :' . $d['pieces'][0]); break; } } else { switch ($d['command']) { case '376': case '422': self::send('JOIN ' . self::$channel); break; case 'privmsg': if (strtolower($d['target']) == self::$channel) { $rawmessage = $d['pieces'][0]; $message = str_replace("", '', $rawmessage); $message = preg_replace('/\\003(\\d\\d?(,\\d\\d?)?)?/', '', $message); $data = parseFeed($message); if ($data === false) { return; } $data['line'] = $message; $data['rawline'] = $rawmessage; if (stripos('N', $data['flags']) !== false) { self::bail($data, 'New article'); return; } $stalkchannel = array(); foreach (Globals::$stalk as $key => $value) { if (myfnmatch(str_replace('_', ' ', $key), str_replace('_', ' ', $data['user']))) { $stalkchannel = array_merge($stalkchannel, explode(',', $value)); } } foreach (Globals::$edit as $key => $value) { if (myfnmatch(str_replace('_', ' ', $key), str_replace('_', ' ', ($data['namespace'] == 'Main:' ? '' : $data['namespace']) . $data['title']))) { $stalkchannel = array_merge($stalkchannel, explode(',', $value)); } } $stalkchannel = array_unique($stalkchannel); foreach ($stalkchannel as $chan) { IRC::say($chan, 'New edit: [[' . ($data['namespace'] == 'Main:' ? '' : $data['namespace']) . $data['title'] . ']] https://en.wikipedia.org/w/index.php?title=' . urlencode($data['namespace'] . $data['title']) . '&diff=prev&oldid=' . urlencode($data['revid']) . ' * ' . $data['user'] . ' * ' . $data['comment']); } switch ($data['namespace'] . $data['title']) { case 'User:'******'/Run': Globals::$run = Api::$q->getpage('User:'******'/Run'); break; case 'Wikipedia:Huggle/Whitelist': Globals::$wl = Api::$q->getpage('Wikipedia:Huggle/Whitelist'); break; case 'User:'******'/Optin': Globals::$optin = Api::$q->getpage('User:'******'/Optin'); break; case 'User:'******'/AngryOptin': Globals::$aoptin = Api::$q->getpage('User:'******'/AngryOptin'); break; } if ($data['namespace'] != 'Main:' and !preg_match('/\\* \\[\\[(' . preg_quote($data['namespace'] . $data['title'], '/') . ')\\]\\] \\- .*/i', Globals::$optin)) { self::bail($data, 'Outside of valid namespaces'); return; } echo 'Processing: ' . $message . "\n"; Process::processEdit($data); } break; } } }
public static function processEditThread($change) { $change['edit_status'] = 'not_reverted'; if (!isset($s)) { $change['edit_score'] = 'N/A'; } else { $change['edit_score'] = $s; } if (!isVandalism($change['all'], $s)) { Feed::bail($change, 'Below threshold', $s); return; } echo 'Is ' . $change['user'] . ' whitelisted ?' . "\n"; if (Action::isWhitelisted($change['user'])) { Feed::bail($change, 'Whitelisted', $s); return; } echo 'No.' . "\n"; $reason = 'ANN scored at ' . $s; $heuristic = ''; $log = null; $diff = 'https://en.wikipedia.org/w/index.php' . '?title=' . urlencode($change['title']) . '&diff=' . urlencode($change['revid']) . '&oldid=' . urlencode($change['old_revid']); $report = '[[' . str_replace('File:', ':File:', $change['title']) . ']] was ' . '[' . $diff . ' changed] by ' . '[[Special:Contributions/' . $change['user'] . '|' . $change['user'] . ']] ' . '[[User:'******'user'] . '|(u)]] ' . '[[User talk:' . $change['user'] . '|(t)]] ' . $reason . ' on ' . gmdate('c'); $oftVand = unserialize(file_get_contents('oftenvandalized.txt')); if (rand(1, 50) == 2) { foreach ($oftVand as $art => $artVands) { foreach ($artVands as $key => $time) { if (time() - $time > 2 * 24 * 60 * 60) { unset($oftVand[$art][$key]); } } } } $oftVand[$change['title']][] = time(); if (count($oftVand[$change['title']]) >= 30) { IRC::say('reportchannel', '!admin [[' . $change['title'] . ']] has been vandalized ' . count($oftVand[$change['title']]) . ' times in the last 2 days.'); } file_put_contents('oftenvandalized.txt', serialize($oftVand)); //IRC::say( 'debugchannel', 'Possible vandalism: ' . $change[ 'title' ] . ' changed by ' . $change[ 'user' ] . ' ' . $reason . '(' . $s . ')' ); //IRC::say( 'debugchannel', '( https://en.wikipedia.org/w/index.php?title=' . urlencode( $change[ 'title' ] ) . '&action=history | ' . $change[ 'url' ] . ' )' ); $ircreport = "15[[07" . $change['title'] . "15]] by \"03" . $change['user'] . "15\" (12 " . $change['url'] . " 15) 06" . $s . "15 ("; checkMySQL(); $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)'; mysql_query($query, Globals::$mysql); $change['mysqlid'] = mysql_insert_id(); echo 'Should revert?' . "\n"; list($shouldRevert, $revertReason) = Action::shouldRevert($change); $change['revert_reason'] = $revertReason; if ($shouldRevert) { echo 'Yes.' . "\n"; $rbret = Action::doRevert($change); if ($rbret !== false) { $change['edit_status'] = 'reverted'; RedisProxy::send($change); //IRC::say( 'debugchannel', 'Reverted. (' . ( microtime( true ) - $change[ 'startTime' ] ) . ' s)' ); IRC::say('debugchannel', $ircreport . "04Reverted15) (13" . $revertReason . "15) (02" . (microtime(true) - $change['startTime']) . " 15s)"); Action::doWarn($change, $report); checkMySQL(); mysql_query('UPDATE `vandalism` SET `reverted` = 1 WHERE `id` = \'' . mysql_real_escape_string($change['mysqlid']) . '\'', Globals::$mysql); Feed::bail($change, $revertReason, $s, true); } else { $change['edit_status'] = 'beaten'; $rv2 = API::$a->revisions($change['title'], 1); if ($change['user'] != $rv2[0]['user']) { //IRC::say( 'debugchannel', 'Grr! Beaten by ' . $rv2[ 0 ][ 'user' ] ); RedisProxy::send($change); IRC::say('debugchannel', $ircreport . "03Not Reverted15) (13Beaten by " . $rv2[0]['user'] . "15) (02" . (microtime(true) - $change['startTime']) . " 15s)"); checkMySQL(); 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']) . '\')', Globals::$mysql); Feed::bail($change, 'Beaten by ' . $rv2[0]['user'], $s); } } } else { RedisProxy::send($change); IRC::say('debugchannel', $ircreport . "03Not Reverted15) (13" . $revertReason . "15) (02" . (microtime(true) - $change['startTime']) . " 15s)"); Feed::bail($change, $revertReason, $s); } }