#!/usr/bin/php
'secret'), array());
ircConf::setChannel("#kohana", "+ntR", array(), array());
ircConf::setChannel("#kohanatest", "+ntR", array(), array());
/** Log/Debug, when TRUE messages will written to the logfile */
define("ircDoLog", true);
/** Log raw IRC output when in debug mode */
define("ircDebug", false);
$irc = new ircBot;
/** ADD CALLBACKS
* This is where the bot gets its functionality.
* See comments & code below for writing callback functions */
$irc->addCallback(onChanMsg, "channelResponses");
$irc->addCallback(onChanMsg, "onMsgCheck");
$irc->addCallback(onOp, "onOpCheck");
//$irc->addCallback(onMode, "onModeCheck");
$irc->addCallback(onTopic, "onTopicCheck");
$irc->addCallback(onNotice, "onNoticeCheck");
$irc->addCallback(onPrivMsg, "onPrivMsgCheck");
$irc->addCallback(onJoin, "onEventCheck");
$irc->addCallback(onKick, "onEventCheck");
$irc->addCallback(onPart, "onEventCheck");
$irc->addCallback(onQuit, "onEventCheck");
$irc->addCallback(onKill, "onEventCheck");
/** Finally start our bot and connect to IRC :) */
$irc->init();
function channelResponses(&$bot, $nick, $ident, $host, $channel, $text) {
// ignore CIA bot
if (preg_match('/^CIA-\d+/', $nick)) return;
if (preg_match("/^".$GLOBALS["ircConf"]["botNick"].".*suck/", $text)) {
// someone said "KohanaTrac sucks"
$bot->provMsg($channel, 'No, '.$nick.', you suck');
return;
}
$direct_msg = false;
if (preg_match("/^".$GLOBALS["ircConf"]["botNick"]."[:,\- ]/", $text)) {
// this msg was directed at the bot
$direct_msg = true;
// replace our name (interferes with wiki links)
$text = str_replace($GLOBALS["ircConf"]["botNick"],"",$text);
}
if (preg_match('/(?log('Got possibly changeset link: '.$matches[0]);
if (false !== ($submatch = scrapeUrl('http://'.TRACURL.'/changeset/'.$matches[1], '/id="searchable">
(.*)<\/p>/ms'))) {
// have to call html_entity_decode() twice beacuse it puts stuff like "
$desc = html_entity_decode(strip_tags(html_entity_decode($submatch[1])));
// get rid of extra spaces, and newlines
$desc = trim( str_replace(array("\n","\r"), array(" ",""), $desc) );
if (strlen($desc) > 60) {
// trim if it's over 60, and show we trimmed it
$desc = substr($desc,0,60).'...';
}
if (!checkIgnore($matches[0]) || $direct_msg) {
$bot->privMsg($channel, 'Revision '.$matches[1].' at http://'.TRACURL.'/changeset/'.$matches[1].': '.$desc);
}
}
}
if (preg_match('/(?log('Got possibly wiki link: '.$matches[0].' checking http://'.TRACURL.'/wiki/'.$matches[0]." = ".checkUrl('http://'.TRACURL.'/wiki/'.$matches[0]));
if (checkUrl('http://'.TRACURL.'/wiki/'.$matches[0]) == 200) {
if (!checkIgnore($matches[0]) || $direct_msg) {
$bot->privMsg($channel, 'Wiki page '.$matches[0].' at http://'.TRACURL.'/wiki/'.$matches[0]);
}
}
}
if (preg_match('/(?log('Got possibly ticket link: '.$matches[0]);
if (false !== ($submatch = scrapeUrl('http://'.TRACURL.'/ticket/'.$matches[1],
//'/
(.*)<\/h2>.*(.*)<\/h3>/msU') )) {
'/(.*)<\/span>.*(.*)<\/h2>/msU') )) {
$bot->log("Its a link.. posting maybe");
$status = html_entity_decode(strip_tags(html_entity_decode($submatch[1])));
if (!checkIgnore($matches[0]) || $direct_msg) {
$bot->log("Not ignoring, posting for sure");
$bot->privMsg($channel, 'Ticket '.$matches[1].' at http://'.TRACURL.'/ticket/'.$matches[1].': '.$submatch[2].' '.$status);
}
}
}
}
function onMsgCheck(&$bot, $nick, $ident, $host, $channel, $text) {
checkRss($bot);
}
function onOpCheck(&$bot, $nick, $ident, $host, $channel, $user) {
checkRss($bot);
}
function onEventCheck(&$bot, $nick, $ident, $host, $channelOrQuit = null) {
checkRss($bot);
}
function onTopicCheck(&$bot, $nick, $ident, $host, $channel, $topic) {
checkRss($bot);
}
function onNoticeCheck(&$bot, $nick, $ident, $host, $dest, $text) {
checkRss($bot);
}
function onPrivMsgCheck(&$bot, $nick, $ident, $host, $us, $text) {
checkRss($bot);
}
function checkRss(&$bot) {
static $lastchecked;
static $lastitem;
if (!isset($lastchecked) || ($lastchecked < time() - RSS_INTERVAL)) {
$bot->log('Checking RSS feed..');
$rss = new lastRSS;
$rss->cache_dir = '';
$rss->cp = 'US-ASCII';
//$rssurl = 'http://'.TRACURL.'/timeline?milestone=on&ticket=on&changeset=on&wiki=on&max=50&daysback=1&format=rss';
$rssurl = 'http://'.TRACURL.'/timeline?milestone=on&ticket=on&changeset=on&wiki=on&max=50&daysback=1&format=rss';
if ($rs = $rss->get($rssurl)) {
if (!isset($lastitem)) {
$lastitem = (isset($rs['items'][0]) ? md5($rs['items'][0]['title']) : '');
} else {
$messages = array();
foreach ($rs['items'] as $item) {
if (md5($item['title']) == $lastitem) {
// don't show any more
break;
}
$title = preg_replace(
array(
'/(? 60) {
// trim if it's over 60, and show we trimmed it
$desc = substr($desc,0,60).'...';
}
$messages[] = $title.': '.$desc.' ('.$item['pubDate'].')';
}
}
if (count($messages) > 0) {
// send them backwards, because we processed the rss forwards
foreach (array_reverse($messages) as $message) {
$bot->privMsg('#kohana-dev', $message);
}
}
// set the lastitem to the first entry now
$lastitem = md5($rs['items'][0]['title']);
}
} else {
// set $lastitem to something, so when we do get something, it will print it
$lastitem = "nadda";
}
$lastchecked = time();
}
}
function checkUrl($url) {
$u = parse_url($url);
if (empty($u['port'])) {
switch($u['scheme']) {
case 'http': $u['port'] = 80; break;
case 'https': $u['port'] = 443; break;
default: return false;
}
}
if (!($s = fsockopen($u['host'],$u['port']))) {
return false;
}
$request = "HEAD ".$u['path']." HTTP/1.1\r\n";
$request .= "Host: ".$u['host']."\r\n";
$request .= "Connection: Close\r\n\r\n";
fwrite($s, $request);
$data = '';
while (!feof($s)) {
$data .= fgets($s, 1024);
}
fclose($s);
if (preg_match('/HTTP\/1.[01] (\d+)/', $data, $matches)) {
return $matches[1];
}
return false;
}
function replace_wiki_url($matches) {
if (checkUrl('http://'.TRACURL.'/wiki/'.$matches[0]) == 200) {
return 'http://'.TRACURL.'/wiki/'.$matches[0];
} else {
return $matches[0];
}
}
function scrapeUrl($url, $regex) {
$u = parse_url($url);
if (empty($u['port'])) {
switch($u['scheme']) {
case 'http': $u['port'] = 80; break;
case 'https': $u['port'] = 443; break;
default: return false;
}
}
if (!($s = fsockopen($u['host'],$u['port']))) {
return false;
}
$request = "GET ".$u['path']." HTTP/1.1\r\n";
$request .= "Host: ".$u['host']."\r\n";
$request .= "Connection: Close\r\n\r\n";
fwrite($s, $request);
$data = '';
while (!feof($s)) {
$data .= fgets($s, 1024);
}
fclose($s);
if (preg_match($regex, $data, $matches)) {
return $matches;
}
return false;
}
// return true if we said this link within IGNORE_TIME seconds
function checkIgnore($link) {
global $irc;
static $ignoring;
if (!isset($ignoring)) $ignoring = array();
foreach ($ignoring as $key=>$time) {
if ($time < time() - IGNORE_TIME) {
$irc->log("No longer ignoring \"$key\"");
unset($ignoring[$key]);
}
}
if (!isset($ignoring[$link])) {
$ignoring[$link] = time();
$irc->log("Now ignoring \"$link\" for ".IGNORE_TIME."s");
return false;
}
$irc->log("Currently ignoring \"$link\"");
return true;
}