Miscellany
public text v1 · immutable<?php
error_reporting(E_ALL);
if (!file_exists('SVNBot.ini')) die('Cannot find configuration file "SVNBot.ini".');
$_CONF = parse_ini_file('SVNBot.ini', true);
$admin = $_CONF['config']['admin'];
$autorejoin = (substr(strtolower($_CONF['config']['autorejoin']), 0, 1) == 'y');
$channels = $_CONF['channels'];
$interval = (empty($_CONF['config']['interval']) ? 1000 : $_CONF['config']['interval']);
$nick = $_CONF['config']['nick'];
$pass = $_CONF['config']['pass'];
$repos = $_CONF['repos'];
$subversion = $_CONF['config']['svn'];
$trigger = (empty($_CONF['config']['trigger']) ? ':' : $_CONF['config']['trigger']);
$err = '';
if (empty($channels)) $err .= 'You must specify at least one channel.' . chr(10);
if (empty($nick)) $err .= 'You must specify a nick for the bot.' . chr(10);
if (empty($subversion)) $err .= 'You must specify the path to your Subversion\'s /bin directory.' . chr(10);
if (!empty($err)) die($err);
include('SmartIRC.php');
$irc = new Net_SmartIRC();
class SVNbot {
var $rev;
function onLoad() {
global $repos, $subversion;
$this->rev = array();
foreach ($repos as $repo => $path) {
if (is_file($path . 'format') && strpos($path, ' ') === false) {
$tmp[str_replace(' ', '_', $repo)] = $path;
} else {
echo 'I cannot watch repository "' . $repo . '".';
ob_flush();
}
}
if (empty($tmp)) {
echo 'I will not be watching any repositories.' . chr(10);
ob_flush();
}
$repos = $tmp;
if (!empty($repos)) {
foreach ($repos as $repo => $path) {
$this->rev[$repo] = 0;
if (is_file($path . 'format')) {
exec('"' . $subversion . 'svnlook" youngest ' . $path, $svninfo);
$this->rev[$repo] = $svninfo[0];
unset($svninfo);
}
}
}
}
function command(&$irc, &$data) {
global $repos, $trigger;
$message = explode(' ', $data->message);
if (strtolower($message[0]) == strtolower($trigger) . 'svn') {
if (count($message) == 1) {
$reply = 'I am currently watching the following repositor';
if (count($repos) == 1) {
$reply .= 'y: ';
} else {
$reply .= 'ies: ';
}
foreach ($repos as $repo => $path) {
$reply .= $repo . ' ';
}
$irc->message(SMARTIRC_TYPE_CHANNEL, $data->channel, trim($reply));
} else {
if (array_key_exists($message[1], $repos)) {
$msg = $message;
$rev = -1;
if (count($msg) > 2) {
if (is_numeric($msg[2]) && intval($msg[2]) == $msg[2] && $msg[2] <= $this->rev[$msg[1]] && $msg[2] >
-1) {
$rev = $msg[2];
} else {
$rev = $this->rev[$msg[1]];
}
} else {
$rev = $this->rev[$msg[1]];
}
$info = $this->getRepoInfo($repos[$message[1]], $rev);
if ($info !== false) {
list($blank, $author, $date, $log, $added, $deleted, $updated, $diff) = $info;
$message = str_replace('_', ' ', $msg[1]) . ' Revision ' . $rev . ' - ';
$message .= 'Author: ' . $author . ' - ';
$message .= 'Date: ' . date('m/d/y H:i:s', $date) . ' - ';
if (count($added) + count($deleted) + count($updated) > 0) {
if (count($added) + count($deleted) + count($updated) > 5) {
if (count($added) > 0) $message .= count($added) . ' added, ';
if (count($deleted) > 0) $message .= count($deleted) . ' deleted, ';
if (count($updated) > 0) $message .= count($updated) . ' updated, ';
} else {
for ($i = 0; $i < count($added); $i++) {
$message .= $added[$i];
if ($i == count($added) - 1) {
$message .= ' added, ';
} else if ($i == count($added) - 2) {
if (count($added) != 2) {
$message .= ',';
}
$message .= ' & ';
} else {
$message .= ', ';
}
}
for ($i = 0; $i < count($deleted); $i++) {
$message .= $deleted[$i];
if ($i == count($deleted) - 1) {
$message .= ' deleted, ';
} else if ($i == count($deleted) - 2) {
if (count($deleted) != 2) {
$message .= ',';
}
$message .= ' & ';
} else {
$message .= ', ';
}
}
for ($i = 0; $i < count($updated); $i++) {
$message .= $updated[$i];
if ($i == count($updated) - 1) {
$message .= ' updated, ';
} else if ($i == count($updated) - 2) {
if (count($updated) != 2) {
$message .= ',';
}
$message .= ' & ';
} else {
$message .= ', ';
}
}
}
$message = trim(substr($message, 0, -2)) . ' - ';
} else {
$message .= 'no changes - ';
}
$log = str_replace(chr(10), ' ', $log);
if (strlen($log) > 300) {
$log = substr($log, 0, 295) . '[...]';
}
$message .= 'Log: ' . $log;
}
$irc->message(SMARTIRC_TYPE_CHANNEL, $data->channel, $message);
} else {
$irc->message(SMARTIRC_TYPE_CHANNEL, $data->channel, 'I am not watching repository "' . $message[1] . '".');
}
}
}
}
function timer(&$irc) {
global $autorejoin, $channels, $repos, $subversion;
foreach ($repos as $repo => $path) {
if (is_file($path . 'format')) {
exec('"' . $subversion . 'svnlook" youngest ' . $path, $svninfo);
$rev = $svninfo[0];
unset($svninfo);
if ($rev > $this->rev[$repo]) {
$info = $this->getRepoInfo($path);
if ($info !== false) {
list($blank, $author, $date, $log, $added, $deleted, $updated, $diff) = $info;
$revision = $this->rev[$repo] = $rev;
$message = str_replace('_', ' ', $repo) . ' Commit - ';
$message .= 'Author: ' . $author . ' - ';
$message .= 'Revision: ' . $revision . ' - ';
if (count($added) + count($deleted) + count($updated) > 0) {
if (count($added) + count($deleted) + count($updated) > 3) {
if (count($added) > 0) $message .= count($added) . ' added, ';
if (count($deleted) > 0) $message .= count($deleted) . ' deleted, ';
if (count($updated) > 0) $message .= count($updated) . ' updated, ';
} else {
for ($i = 0; $i < count($added); $i++) {
$message .= $added[$i];
if ($i == count($added) - 1) {
$message .= ' added, ';
} else if ($i == count($added) - 2) {
if (count($added) != 2) {
$message .= ',';
}
$message .= ' & ';
} else {
$message .= ', ';
}
}
for ($i = 0; $i < count($deleted); $i++) {
$message .= $deleted[$i];
if ($i == count($deleted) - 1) {
$message .= ' deleted, ';
} else if ($i == count($deleted) - 2) {
if (count($deleted) != 2) {
$message .= ',';
}
$message .= ' & ';
} else {
$message .= ', ';
}
}
for ($i = 0; $i < count($updated); $i++) {
$message .= $updated[$i];
if ($i == count($updated) - 1) {
$message .= ' updated, ';
} else if ($i == count($updated) - 2) {
if (count($updated) != 2) {
$message .= ',';
}
$message .= ' & ';
} else {
$message .= ', ';
}
}
}
$message = trim(substr($message, 0, -2)) . ' - ';
} else {
$message .= 'no changes - ';
}
$log = str_replace(chr(10), ' ', $log);
if (strlen($log) > 200) {
$log = substr($log, 0, 195) . '[...]';
}
$message .= 'Log: ' . $log;
foreach ($channels as $channel) {
if ($irc->channel($channel) === false) {
if ($autorejoin) {
$irc->join($channel);
} else {
$channellist = array();
foreach ($channels as $chan) {
if ($chan != $channel) $channellist[] = $chan;
}
$channels = $channellist;
continue;
}
}
$irc->message(SMARTIRC_TYPE_CHANNEL, $channel, $message);
}
}
}
}
}
}
function getRepoInfo($path, $revision = -1) {
global $subversion;
if ($revision > -1) {
$rev = ' -r ' . $revision;
} else {
$rev = '';
}
if (is_dir($path)) {
exec('"' . $subversion . 'svnlook" info ' . $path . $rev, $svninfo);
$author = trim($svninfo[0]);
$date = strtotime(substr($svninfo[1], 0, 25));
$log = '';
for ($i = 3; $i < count($svninfo); $i++) {
$log .= $svninfo[$i] . chr(10);
}
$log = trim($log);
unset($svninfo);
exec('"' . $subversion . 'svnlook" changed ' . $path . $rev, $svninfo);
$added = array();
$deleted = array();
$updated = array();
foreach ($svninfo as $line) {
if (empty($line)) {
continue;
} else if (strtoupper(substr($line, 0, 1)) == 'A') {
$added[] = trim(substr($line, 1));
} else if (strtoupper(substr($line, 0, 1)) == 'D') {
$deleted[] = trim(substr($line, 1));
} else if (strtoupper(substr($line, 0, 1)) == 'U') {
$updated[] = trim(substr($line, 1));
}
}
unset($svninfo);
exec('"' . $subversion . 'svnlook" diff ' . $path . $rev . ' --no-diff-deleted', $svninfo);
$diff = implode(chr(10), $svninfo);
unset($svninfo);
return array('', $author, $date, $log, $added, $deleted, $updated, $diff);
}
}
function invite(&$irc, &$data) {
global $channels;
$channels[] = $data->message;
$irc->join($data->message);
$irc->message(SMARTIRC_TYPE_CHANNEL, $data->message, 'Thanks for inviting me, ' . $data->nick . '!');
}
function quit(&$irc, &$data) {
global $admin;
if (strtolower($data->nick) == strtolower($admin)) {
exit();
}
}
}
$svnbot = new SVNbot();
$svnbot->onLoad();
$tmpdata = &new Net_SmartIRC_data();
$tmpdata->nick = $admin;
register_shutdown_function(array($svnbot, 'quit'), $irc, $tmpdata);
$temp_arr = array('nick', $admin);
register_shutdown_function(array($svnbot, 'quit'), $irc, $temp_arr);
$irc->setCtcpVersion('SVNBot (by Theme97) running on PHP ' . current(explode('.', phpversion())));
$irc->registerActionhandler(SMARTIRC_TYPE_CHANNEL, '/^' . $trigger . 'svn.*/i', $svnbot, 'command');
$irc->registerActionhandler(SMARTIRC_TYPE_CHANNEL, '/^' . $trigger . 'quit/i', $svnbot, 'quit');
$irc->registerActionhandler(SMARTIRC_TYPE_INVITE, '.*', $svnbot, 'invite');
if (!empty($repos)) $irc->registerTimehandler($interval, $svnbot, 'timer');
$irc->connect('irc.freenode.net', 6667);
if ($pass == '') $pass = null;
$irc->login($nick, $nick, 0, $nick, $pass);
$irc->join($channels);
$irc->listen();
$irc->disconnect();
?>