*/ class Client { protected $connected = false; protected $socket = null; protected $config = null; protected $blatech = null; /** * Constructor to load up a config file, and create a socket connection * and register the client to the IRC server. Then join then the channel * * @author Phil Burton * @param $config array An array of config options * @todo Use a config object and create a isConfigValid function */ public function __construct($config) { // Create the client from the given config $this->config = parse_ini_file($config); if ($error = $this->isSocket() === true) { $this->userCommand(); $ping = $this->nickCommand(); $this->pongCommand($ping); $this->connected = true; $this->identifyCommand(); $this->joinCommand(); } else { var_dump($error); die(); } } /** * Checks to see if a socket has already been created * If not, it creates the new socket based on the config * and then returns true if the socket is created * * @author Phil Burton * @return bool True if socket is created otherwise false * @todo gracefully return false if the socket didn't get created */ protected function isSocket() { if (!$this->socket) { // Try and create socket if (($this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) { echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n"; die(); } if (!socket_set_option($this->socket, SOL_SOCKET, SO_REUSEADDR, 1)) { echo socket_strerror(socket_last_error($this->socket)); } if (socket_connect($this->socket, $this->config['server'], $this->config['port']) === false) { echo "socket_connect() failed: reason: " . socket_strerror(socket_last_error($this->socket)) . "\n"; } } $this->getResponse(); return true; } /** * Send the USER command to the IRC server using the config to get the * required details. * * @author Phil Burton * @todo Create sendCommand function to handle generic message sending */ protected function userCommand() { socket_write($this->socket, "USER ". $this->config["username"] . ' ' . $this->config['hostname'] . ' ' . $this->config['servername'] . " :" . $this->config['realname'] . "\r\n"); } /** * Send the NICK command to the IRC server using the config to get the * required details. * * @author Phil Burton * @todo Create sendCommand function to handle generic message sending */ protected function nickCommand() { // Set the nick socket_write($this->socket, "NICK ". $this->config["username"] . "\r\n"); $response = $this->getResponse(); var_dump('NICK COMMAND RESPONSE: '); var_dump($response); return $response; // save response to use in pong response } /** * Send the PONG command to the IRC server using the config to get the * required details. If the ping param is set, then send that too. * * @author Phil Burton * @param @ping String A message to send along with the pong response * @todo Create sendCommand function to handle generic message sending * @todo Create better way to handle respones, and log them */ protected function pongCommand($ping = null) { // Pong the server if (!$ping) { socket_write($this->socket, "PONG"); } else { socket_write($this->socket, "PONG $ping\r\n"); } if (!$this->connected) { var_dump('PONG COMMAND RESPONSE: '); $this->getResponse(); } } /** * Send a mesage to the IRC server, messaging the nick server to identify * the client with the config details. * * @author Phil Burton * @todo Create sendCommand function to handle generic message sending * @todo Create better way to handle respones, and log them */ protected function identifyCommand() { // Identify the user socket_write($this->socket, "PRIVMSG ". "nickserv identify " . $this->config["pass"] . "\r\n"); var_dump('IDENTIFY COMMAND RESPONSE: '); $this->getResponse(); } /** * Send a JOIN command to the IRC server to join a channel based on the * config details * * @author Phil Burton * @todo Create sendCommand function to handle generic message sending * @todo Create better way to handle respones, and log them * @todo Find a way to support multiple channels */ protected function joinCommand() { // Join the channel socket_write($this->socket, "JOIN ". $this->config["channel"] . "\r\n"); var_dump('JOIN COMMAND RESPONSE: '); $this->getResponse(); } /** * Read the socket, waiting for an incoming message from the IRC * server. Display memory usage here. Dump and return the response. * * @author Phil Burton * @return String The response from the server * @todo Create better way to handle respones, and log them */ protected function getResponse() { var_dump("memory: " . memory_get_usage()/1000 . 'KB'); $response = ""; while(true) { sleep(1); $response .= socket_read($this->socket,4096); if ($response == 0) { echo($response) . "\n"; return $response; } } } /** * Send a PRIVMSG command to the IRC server to message a channel based on * the config details. * * @author Phil Burton * @todo Create sendCommand function to handle generic message sending * @todo Create better way to handle respones, and log them * @todo Find a way to support multiple channels * @todo Find a way to support private and channel message sending */ public function msgCommand($msg) { socket_write($this->socket, "PRIVMSG ". $this->config["channel"] . ' ' . $msg . "\r\n"); } /** * The main loop of the Client. Constantly listen for incoming messages * from the IRC server; respond to pings, and look out for bot commands. * * @author Phil Burton * @todo Create sendCommand function to handle generic message sending * @todo Create better way to handle respones, and log them * @todo Find a way to support multiple channels * @todo Find a way to support private and channel message sending */ public function loop() { while (true) { $message = explode(" ", $this->getResponse()); if ($message[0] == 'PING') { $this->pongCommand($message[1]); } else { if (strpos($message[3], ":!") === 0) { $args = ''; if(($count = count($message)) > 4) { for ($i = 4; $i < $count; $i++ ) { $args .= rtrim($message[$i]) . ' '; } $args = rtrim($args); } $this->msgCommand($this->blatech->runCommand($message, $args)); } } $message = null; } } /** * Check for an existing Blatech object, if it doesn't exist, create it * with the config path that is passed. * * @author Phil Burton * @return Blatech The Blatech object */ public function loadBlatech($config) { if (null == $this->blatech) { include_once("Blatech.php"); $this->blatech = new Blatech($config); } return $this->blatech; } } // Create a new client object $client = new Client('Client.ini'); // Load up the blatech Object $client->loadBlatech('Blatech.ini'); // Send a hello command to the channel $client->msgCommand('In The Rear, With The Gear!'); // Start the main loop $client->loop();