All pastes #904669 Raw Edit

Stuff

public php v1 · immutable
·published 2008-02-15 03:52 UTC
rendered paste body
#!/usr/bin/php<?phpdefine("RSS_INTERVAL", 300); // seconds between downloading RSS changelogdefine("IGNORE_TIME", 60*15); // seconds we don't repeat linksdefine('TRACURL', 'trac.kohanaphp.com');define("ircBotPath", str_replace("\\", "/", dirName(__FILE__)));include(ircBotPath."/lib/ircBot.class.php");include('lastRSS.inc.php');if (version_compare(phpversion(),'4.3.0','<') || !defined("STDIN")) {        define('STDIN',fopen("php://stdin","r"));        define('STDOUT',fopen("php://stdout","r"));        define('STDERR',fopen("php://stderr","r"));        register_shutdown_function( create_function( '' , 'fclose(STDIN); fclose(STDOUT); fclose(STDERR); return true;' ) );}/************************  Configuration  ************************/ircConf::set("botNick", "KohanaTrac");       /** Bot nick */ircConf::set("botName", "Kohana Trac Bot");  /** Bot's IRC name */ircConf::set("botIdent", "TracBot");      /** Bot's ident *//** NickServ password, comment out if you don't have one.  NOTE: this is also used when the bot NickName is taken to try ghost it  with NickServ, only when set *///ircConf::set("botNickServPass", "secret");/** Servers to connect to - MUST BE ARRAY()!!! Used for rotation */ircConf::set("servers", array("irc.freenode.net"));ircConf::set("serverPort", 6667); /** Server port */ircConf::set("stayAlive", true); /** Stay-Alive - Keep trying connections *//** Some networks and people don't like bots */ircConf::set("versionReply", "greg's fantastic trac bot");/** Bot channel configuration, this is a new requirement, channel users need tobe configured for each channel, users list MUST be an array */ircConf::setChannel("#kohana-dev", "+ntR", array('keyword'=>'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('/(?<!\w)r(\d+)(?!\w)/', $text, $matches) ||          preg_match('/(?<!\w)\[(\d+)\](?!\w)/', $text, $matches)) {                $bot->log('Got possibly changeset link: '.$matches[0]);                if (false !== ($submatch = scrapeUrl('http://'.TRACURL.'/changeset/'.$matches[1], '/id="searchable"><p>(.*)<\/p>/ms'))) {                        // have to call html_entity_decode() twice beacuse it puts stuff like &amp;#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('/(?<![\w\/])([A-Z][a-z]+)([A-Z0-9][a-z0-9]*)+/', $text, $matches)) {                $bot->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('/(?<!\w)(?:#|bug |ticket )(\d{1,4})(?!\w)/', $text, $matches)) {                $bot->log('Got possibly ticket link: '.$matches[0]);                if (false !== ($submatch = scrapeUrl('http://'.TRACURL.'/ticket/'.$matches[1],                  //'/<h2 class="summary">(.*)<\/h2>.*<h3 class="status">(.*)<\/h3>/msU') )) {                  '/<span class="status">(.*)<\/span>.*<h2 class="summary">(.*)<\/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(                                                        '/(?<!\w)r(\d+)(?!\w)/',                                                        '/(?<!\w)\[(\d+)\](?!\w)/',                                                        '/(?<!\w|&)#(\d+)(?!\w)/',                                                ),                                                array(                                                        'http://'.TRACURL.'/changeset/$1',                                                        'http://'.TRACURL.'/changeset/$1',                                                        'http://'.TRACURL.'/ticket/$1',                                                ),                                                $item['title']);                                        $title = preg_replace_callback('/([A-Z][a-z]+)([A-Z0-9][a-z0-9]+)*/', 'replace_wiki_url', $title);                                        if (substr($title,0,9) == 'Changeset') {                                                // changeset titles include a description                                                $messages[] = $title.' ('.$item['pubDate'].')';                                        } else {                                                // have to call html_entity_decode() twice beacuse it puts stuff like &amp;#34;                                                $desc = html_entity_decode(strip_tags(html_entity_decode($item['description'])));                                                // 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).'...';                                                }                                                $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 secondsfunction 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;}