Main module | > Module written by Manick | > Module Version Number: 2.2.0 +--------------------------------------------------------------------------- | > 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. +--------------------------------------------------------------------------- | Changes | =======------- | > If you wish to suggest or submit an update/change to the source | > code, email me at manick@manekian.com with the change, and I | > will look to adding it in as soon as I can. +--------------------------------------------------------------------------- */ error_reporting(E_ALL); set_time_limit(0); $oldDir = getcwd(); chdir("../scripts"); $__logPrefix = "lwBot"; $__loader = array( 'log', 'classloader', 'version', 'game', 'tick', 'config', 'db_connection', 'db_accessor', 'db', 'library' ); require_once('loader.inc'); chdir($oldDir); require('./defines.php'); require('./queue.php'); require('./module.php'); require('./irc.php'); require('./socket.php'); require('./timers.php'); require('./dcc.php'); require('./chat.php'); require('./file.php'); require('./parser.php'); require('./databases/ini.php'); require('./error.php'); require('./connection.php'); require('./remote.php'); final class bot { /* Global socket class used by all bots */ private $socketClass; /* Global process Queue used by all bots, timers, dcc classes */ private $procQueue; /* Whether we are running in background mode or not. (not sure if this is used anymore */ private $background = 0; //contain all the bots private $bots = array(); // save the only one instance of bot (singleton) private static $_instance; public static function getInstance() { if (!isset (self :: $_instance)) { self :: $_instance = new bot(); } return self :: $_instance; } //Main Method private function __construct() { $this->socketClass = new socket(); $this->procQueue = new processQueue(); $this->socketClass->setProcQueue($this->procQueue); $this->readConfig(); } public function launch(){ foreach($this->bots as $bot) { $this->createBot($bot); } try { /* Main program loop */ while (1) { //Get data from sockets, and trigger procQueue's for new data to be read $this->socketClass->handle(); //The bots main process loop. Run everything we need to! $timeout = $this->procQueue->handle(); //Okay, set the socketclass timeout based on the next applicable process if ($timeout !== true) { $this->socketClass->setTimeout($timeout); } //echo $this->procQueue->getNumQueued() . "\n"; //$this->procQueue->displayQueue(); //Aight, if we don't have any sockets open/in use, and //we have no processes in the process queue, then there are //obviously no bots running, so just exit! if ($this->socketClass->getNumSockets() == 0 && $this->procQueue->getNumQueued() == 0) { break; } } } catch (Exception $e) { $this->ircClass->log($e->_toString()); } } public static function addBot($filename){ $bot = bot::getInstance(); $config = bot::parseConfig($filename); if ($config == false) { return false; } $newBot = new botClass(); $newBot->config = $config; $newBot->configFilename = $filename; $bot->bots[] = $newBot; $bot->createBot($newBot); return true; } private function createBot($bot) { $this->connectToDatabase($bot); $bot->socketClass = $this->socketClass; $bot->timerClass = new timers(); $bot->parserClass = new parser(); $bot->dccClass = new dcc(); $bot->ircClass = new irc(); $bot->ircClass->setConfig($bot->config, $bot->configFilename); $bot->ircClass->setSocketClass($this->socketClass); $bot->ircClass->setParserClass($bot->parserClass); $bot->ircClass->setDccClass($bot->dccClass); $bot->ircClass->setTimerClass($bot->timerClass); $bot->ircClass->setProcQueue($this->procQueue); $bot->dccClass->setSocketClass($this->socketClass); $bot->dccClass->setTimerClass($bot->timerClass); $bot->dccClass->setParserClass($bot->parserClass); $bot->dccClass->setProcQueue($this->procQueue); $bot->parserClass->setTimerClass($bot->timerClass); $bot->parserClass->setSocketClass($this->socketClass); $bot->parserClass->setDatabase($bot->db); $bot->timerClass->setIrcClass($bot->ircClass); $bot->timerClass->setSocketClass($this->socketClass); $bot->timerClass->setProcQueue($this->procQueue); $bot->parserClass->init(); //Okay, this function adds the connect timer and starts up this bot class. $bot->ircClass->init(); bot::createChannelArray($bot->ircClass); } private function readConfig() { global $argc, $argv; if ($argc < 2) { $args = array(config::$main['scriptdir'] . "/../ircbot/bot.conf"); } else { $args = $argv; array_shift($args); } $isPasswordEncrypt = false; foreach ($args AS $filename) { if ($filename == "") { continue; } if ($isPasswordEncrypt == true) { die("Encrypted Password: " . md5($filename) . "\nReplace this as 'dccadminpass' in bot.conf!"); } if ($filename == "-c") { $isPasswordEncrypt = true; continue; } if ($filename == "-b" && $this->background != 1) { $this->background = 1; $this->doBackground(); continue; } $config = bot::parseConfig($filename); if ($config == false) { echo "Could not spawn bot $filename"; die(); } $bot = new botClass(); $bot->config = $config; $bot->configFilename = $filename; $this->bots[] = $bot; } if ($isPasswordEncrypt == true) { die("No password submitted on command line! Syntax: bot.php -c \n"); } if (! $this->background && PID != '') { $file = fopen(PID, "w+"); fwrite($file, getmypid()); fclose($file); } } private function connectToDatabase($bot) { if (isset($bot->config['usedatabase'])) { if (!file_exists("./databases/" . $bot->config['usedatabase']. ".php")) { die("Couldn't find the database file! Make sure it exists!"); } require_once("./databases/" . $bot->config['usedatabase']. ".php"); $dbType = $bot->config['usedatabase']; if (!isset($bot->config['dbhost'])) $bot->config['dbhost'] = "localhost"; if (!isset($bot->config['dbuser'])) $bot->config['dbuser'] = "root"; if (!isset($bot->config['dbpass'])) $bot->config['dbpass'] = ""; if (!isset($bot->config['db'])) $bot->config['db'] = "test"; if (!isset($bot->config['dbprefix'])) $bot->config['dbprefix'] = ""; if (!isset($bot->config['dbport'])) { $bot->db = new $dbType($bot->config['dbhost'], $bot->config['db'], $bot->config['dbuser'], $bot->config['dbpass'], $bot->config['dbprefix']); } else { $bot->db = new $dbType($bot->config['dbhost'], $bot->config['db'], $bot->config['dbuser'], $bot->config['dbpass'], $bot->config['dbprefix'], $bot->config['dbport']); } if (!$bot->db->isConnected()) { die("Couldn't connect to database..."); } } } public static function createChannelArray($ircClass) { $channels = $ircClass->getClientConf('channel'); if ($channels != "") { if (!is_array($channels)) { $channels = array($channels); } foreach ($channels AS $channel) { $chan = $channel; $key = ""; if (strpos($channel, chr(32)) !== false) { $channelVars = explode(chr(32), $channel); $chan = $channelVars[0]; $key = $channelVars[1]; } $ircClass->maintainChannel($chan, $key); } } } public static function parseConfig($filename) { $configFPtr = @fopen($filename, "rt"); if ($configFPtr == null) { // echo "Could not find config file '".$filename."'\n"; return false; } $configRaw = ""; try { while (!feof($configFPtr)) { $configRaw .= fgets($configFPtr, 1024); } fclose($configFPtr); } catch (Exception $e) { // echo "A fatal IO Exception occured."; return false; } $config = array(); $configRaw = str_replace("\r", "", $configRaw); $confLines = explode("\n", $configRaw); foreach ($confLines AS $line) { $line = trim($line); if ($line == "" || substr($line, 0, 1) == ";") { continue; } $offsetA = strpos($line, chr(32)); if ($offsetA != false) { $confVar = substr($line, 0, $offsetA); $confParams = substr($line, $offsetA + 1); } else { $confVar = $line; $confParams = ""; } if (preg_match('/__CFG:([a-zA-Z_]+)__/', $confParams, $matches)) { $src = array(); $dst = array(); array_shift($matches); foreach ($matches as $cfgSubst) { array_push($src, "/__CFG:{$cfgSubst}__/"); array_push($dst, config::$main[$cfgSubst]); } $confParams = preg_replace($src, $dst, $confParams); } if (isset($config[$confVar])) { if (!is_array($config[$confVar])) { $prevParam = $config[$confVar]; $config[$confVar] = array(); $config[$confVar][] = $prevParam; } $config[$confVar][] = $confParams; } else { $config[$confVar] = $confParams; } } return $config; } private function doBackground() { $pid = pcntl_fork(); if ($pid == -1) { die("Error: could not fork\n"); } else if ($pid) { if (PID != "") { $file = fopen(PID, "w+"); fwrite($file, $pid); fclose($file); } exit(); // Parent } if (!posix_setsid()) { die("Error: Could not detach from terminal\n"); } fclose(STDIN); fclose(STDOUT); fclose(STDERR); } } $ircBot = bot::getInstance(); $ircBot->launch(); ?>