#!/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 &#34; $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; }