diff options
Diffstat (limited to 'Client.php')
-rw-r--r-- | Client.php | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/Client.php b/Client.php new file mode 100644 index 0000000..cfd0fca --- /dev/null +++ b/Client.php @@ -0,0 +1,248 @@ +<?php + +/** + * A headless, slim IRC Client, that act's as the core of an IRC BOT. + * + * @author Phil Burton <philbeansburton@gmail.com> + */ +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 <philbeansburton@gmail.com> + * @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 <philbeansburton@gmail.com> + * @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 <philbeansburton@gmail.com> + * @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 <philbeansburton@gmail.com> + * @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 <philbeansburton@gmail.com> + * @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 <philbeansburton@gmail.com> + * @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 <philbeansburton@gmail.com> + * @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 <philbeansburton@gmail.com> + * @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 <philbeansburton@gmail.com> + * @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 <philbeansburton@gmail.com> + * @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 <philbeansburton@gmail.com> + * @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(); + |