#!/usr/local/bin/php -q
<?php
/* $Id$
------------------------------------------------------------------
| bot.php |
| ------------------------------------------------------------------ |
| Copyright (C) 2003 Donovan Schönknecht <ds@undesigned.org.za> |
| ------------------------------------------------------------------ |
| Subtility - Configuration, callbacks and implementation |
| ------------------------------------------------------------------ |
| This program is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public License as |
| published by the Free Software Foundation; either version 2 of |
| the License, or (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
| MA 02111-1307 USA |
------------------------------------------------------------------ */
/** README (yes, read this):
Subtility is really more of an IRC framework than an IRC bot.
The idea is to provide an easy, stable interface to IRC, just
add callbacks. Callbacks are called on different IRC events,
such as onOp, onJoin, onQuit, etc.
This file gives examples of callbacks and the implementation of the
callbacks to the ircBot class.
Channel modes are now split up and working properly, currently only
the channel events:
onOp/onDeOp, onVoice/onDeVoice, onBan/onUnban
are registered for channel modes, all other modes will be passed to onMode
individually...
--------------------- GETTING STARTED ---------------------------
The configuration values below will need to be edited, as well
as #!/usr/local/bin/php to your PHP path or run it as
./bot.php &
to put it in the background, then you can
tail -f log/<botNickNameGoesHere>.log
which will show you the log data as it recieves it.
To run your bot in the background, use screen.
To view the raw IRC output subtility recieves, set ircDebug to
true, this will also display any other debug data.
See the callback functions and comments below for an idea of how
the callbacks work. It's fairly simple...
-----------------------------------------------------------------
Please don't hesitate to send corrections, suggestions (preferebly
theoretical/programmatical) or bug reports via my email address
or bug reporter @
http://undesigned.org.za/bugReport/L3Byb2plY3RzL3N1YnRpbGl0eS8%3D
Enjoi!
--ds
*/
/** Find's the root path (don't remove this, it is used by the ircBot class) */
define("ircBotPath", str_replace("\\", "/", dirName(__FILE__)));
include(ircBotPath."/lib/ircBot.class.php");
/************************ Configuration ************************/
ircConf::set("botNick", "Fear_Php"); /** Bot nick */
ircConf::set("botName", "Php Bot"); /** Bot's IRC name */
ircConf::set("botIdent", "Fear"); /** 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", "m1cr0s");
/** Servers to connect to - MUST BE ARRAY()!!! Used for rotation */
ircConf::set("servers", array("irc.swiftirc.net", "server2.network.com"));
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", "mIRC v6.12 Khaled Mardam-Bey");
ircConf::set("versionReply", Php Bot by Fear);
/** Bot user configuration */
ircConf::setUser("myprodol", "fear", "*.fear.users.swiftirc.net", "admin");
ircConf::setUser("Darkone", "marc", "*.mweb.co.za", "plebb");
ircConf::setUser("cynn_", "cynn", "sg.168.*.*", "plebb");
ircConf::setUser("darkness", "blunt", "sg.168.*.*", "plebb");
ircConf::setUser("flipside", "shane", "*.telkomadsl.co.za", "plebb");
ircConf::setUser("web-rebelion", "rebel_boi", "*.blueyonder.co.uk", "plebb");
ircConf::setUser("rory", "rory", "*.absamail.co.za", "plebb");
/** Bot channel configuration, this is a new requirement, channel users need to
be configured for each channel, users list MUST be an array */
ircConf::setChannel("#php", "+ntR", array("autoOp"),
array("myprodol", "Darkone", "web-rebelion", "darkness", "cynn_", "flipside")
);
/** 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(onNotice, "identifyNickServ");
$irc->addCallback(onJoin, "greetOnJoin");
$irc->addCallback(onTopic, "updateTopic");
$irc->addCallback(onPrivMsg, "adminControl");
$irc->addCallback(onChanMsg, "toolNsLookup");
$irc->addCallback(onChanMsg, "channelResponses");
$irc->addCallback(onOp, "secureOps");
$irc->addCallback(onMode, "checkMode");
// multiple functions/events can be declared
$irc->addCallback(onJoin, "lastSeen");
$irc->addCallback(onKick, "lastSeen");
$irc->addCallback(onPart, "lastSeen");
$irc->addCallback(onQuit, "lastSeen");
$irc->addCallback(onKill, "lastSeen");
/** Finally start our bot and connect to IRC :) */
$irc->init();
/****************************************************************************
* CALLBACK FUNCTIONS
****************************************************************************
* Different arguments are passed to the callback function on
* each event, argument 0 is ALWAYS a reference to the ircBot object which
* allows us to access the bot methods.
* Arguments 1/2/3 are typically the users nick/ident/host.
*
* To add a callback, simply call addCallback(event, "yourCallbackFunction")
*
* ---------------------------- Message events ---------------------------
*
* _onPrivMsg(&$bot, $nick, $ident, $host, $dest, $text)
* onChanMsg(&$bot, $nick, $ident, $host, $channel, $text)
* onNotice(&$bot, $nick, $ident, $host, $dest, $text)
* onCTCP/onChanCTCP(&$bot, $nick, $ident, $host, $dest, $data)
* onInvite(&$bot, $nick, $ident, $host, $nick, $channel)
*
* ---------------------------- Channel events ---------------------------
*
* onJoin(&$bot, $nick, $ident, $host, $channel)
* onPart(&$bot, $nick, $ident, $host, $channel)
* onKick(&$bot, $nick, $ident, $host, $channel, $victim, $reason)
* onTopic(&$bot, $nick, $ident, $host, $channel, $topic)
* onQuit(&$bot, $nick, $ident, $host, $quitMsg)
* onKill(&$bot, $nick, $ident, $host, $victim, $text)
*
* ---------------------------- Mode events ------------------------------
*
* onOp/onDeOp(&$bot, $nick, $ident, $host, $channel, $user)
* onVoice/onDeVoice(&$bot, $nick, $ident, $channel, $user)
* onBan/onUnBan(&$bot, $nick, $ident, $host, $channel, $user)
*
* Other modes are passed to onMode:
* onMode(&$bot, $nick, $ident, $host, $channel, $data)
*
****************************************************************************/
function identifyNickServ(&$bot, $nick, $ident, $host, $dest, $text) {
if ($nick == "NickServ" && $dest == ircConf::get("botNick") &&
eregi("This nick is owned", $text)) {
$bot->privMsg("NickServ", "identify ".ircConf::get("botNickServPass"));
}
}
function secureOps(&$bot, $nick, $ident, $host, $channel, $user) {
/** We have to ignore ops by the bot, she seems to have problems
with autoOps, she deops straight after auto-op'ing. */
if (in_array(ircConf::get("botNick"), array($nick, $user))) return;
if (!ircConf::isChannelUser($channel, $nick, $ident, $host)) { // be strict :P
$bot->write("MODE $channel -oo $user $nick");
}
}
function channelResponses(&$bot, $nick, $ident, $host, $channel, $text) {
$text = strToLower($text);
if ($text == "lol") {
$bot->privMsg($channel, "heh");
} elseif ($text == "?") {
$bot->privMsg($channel, "don't ask stupid questions $nick");
}
}
/** Sample tool: "!nslookup 127.0.0.1" OR "!nslookup www.php.net"
NOTE:
Be careful with functions that may take a while to return,
these functions will have to return before the bot will continue.
If the bot were allowed to simutainiously process callbacks,
too many procedures would cause the bot to use large amounts
of resources. */
function toolNsLookup(&$bot, $nick, $ident, $host, $dest, $text) {
if (strToLower(substr($text, 0, 9)) == "!nslookup") {
$lookupHost = str_replace(" ", "", substr($text, 10));
if (@preg_match( // is IP :)
"/^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.".
"(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.".
"(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.".
"(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$/", $lookupHost)) {
if (($returnHost = getHostByAddr($lookupHost)) !== $lookupHost) {
$bot->privMsg($dest, "Resolved $lookupHost to $returnHost");
} else {
$bot->privMsg($dest, "Unable to resolve IP $lookupHost");
}
} else {
if (($returnHost = getHostByName($lookupHost)) !== $lookupHost) {
$bot->privMsg($dest, "Resolved $lookupHost to $returnHost");
} else {
$bot->privMsg($dest, "Unable to resolve $lookupHost");
}
}
}
}
function adminControl(&$bot, $nick, $ident, $host, $us, $text) {
if (ircConf::isUser($nick, $ident, $host, "admin")) {
if ($text == "quit") {
$bot->close($nick." wants me to leave :-(");
exit;
} elseif (substr($text, 0, 3) == "raw") {
$raw = substr($text, 4);
$bot->privMsg($nick, "Writing raw command: $raw");
$bot->write($raw);
} elseif ($text == "join") {
foreach ($GLOBALS["ircConf"]["chans"] as $channel => $data) {
$bot->write("JOIN $channel");
$bot->write("MODE $channel ".$data["modes"]);
} unset($channel, $data);
} else {
$bot->privMsg($nick, "Valid commands:");
$bot->privMsg($nick, "join | quit");
}
}
}
function greetOnJoin(&$bot, $nick, $ident, $host, $channel) {
if ($nick !== ircConf::get("botNick")) { /** ignore ourself */
if (ircConf::isChannelUser($channel, $nick, $ident, $host)) {
$bot->write("MODE $channel +o $nick");
$bot->privMsg($channel, "hey $nick");
}
}
}
function lastSeen(&$bot, $nick, $ident, $host, $channelOrQuit = null) {
if ($nick == ircConf::get("botNick")) return; /** ignore ourself */
$bot->privMsg(ircConf::get("channel"), "Last seen for $nick ($channelOrQuit)");
}
function updateTopic(&$bot, $nick, $ident, $host, $channel, $topic) {
/** insert code to update topic to db here */
$bot->privMsg($channel, "$nick changed the topic to $topic");
}
?>