. */ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } /** * IRC background connection manager for IRC-using queue handlers, * allowing them to send outgoing messages on the right connection. * * Input is handled during socket select loop, Any incoming messages will be handled. * * In a multi-site queuedaemon.php run, one connection will be instantiated * for each site being handled by the current process that has IRC enabled. */ class IrcManager extends ImManager { protected $conn = null; protected $lastPing = null; protected $regChecks = array(); protected $regChecksLookup = array(); /** * Initialize connection to server. * * @return boolean true on success */ public function start($master) { if (parent::start($master)) { $this->connect(); return true; } else { return false; } } /** * Return any open sockets that the run loop should listen * for input on. * * @return array Array of socket resources */ public function getSockets() { $this->connect(); if ($this->conn) { return $this->conn->getSockets(); } else { return array(); } } /** * Idle processing for io manager's execution loop. * Send keepalive pings to server. * * @return void */ public function idle() { if (empty($this->lastPing) || time() - $this->lastPing > 120) { $this->sendPing(); } } /** * Process IRC events that have come in over the wire. * * @param resource $socket Socket to handle input on * @return void */ public function handleInput($socket) { common_log(LOG_DEBUG, 'Servicing the IRC queue.'); $this->stats('irc_process'); try { $this->conn->handleEvents(); } catch (Phergie_Driver_Exception $e) { $this->conn->reconnect(); } } /** * Initiate connection * * @return void */ public function connect() { if (!$this->conn) { $this->conn = new Phergie_StatusnetBot; $config = new Phergie_Config; $config->readArray( array( 'connections' => array( array( 'host' => $this->plugin->host, 'port' => $this->plugin->port, 'username' => $this->plugin->username, 'realname' => $this->plugin->realname, 'nick' => $this->plugin->nick, 'password' => $this->plugin->password, 'transport' => $this->plugin->transporttype, 'encoding' => $this->plugin->encoding ) ), 'driver' => 'statusnet', 'processor' => 'async', 'processor.options' => array('sec' => 0, 'usec' => 0), 'plugins' => array( 'Pong', 'NickServ', 'AutoJoin', 'Statusnet', ), 'plugins.autoload' => true, //'ui.enabled' => true, 'nickserv.password' => $this->plugin->nickservpassword, 'nickserv.identify_message' => $this->plugin->nickservidentifyregexp, 'autojoin.channels' => $this->plugin->channels, 'statusnet.messagecallback' => array($this, 'handle_irc_message'), 'statusnet.regcallback' => array($this, 'handle_reg_response'), 'statusnet.unregregexp' => $this->plugin->unregregexp, 'statusnet.regregexp' => $this->plugin->regregexp ) ); $this->conn->setConfig($config); $this->conn->connect(); $this->lastPing = time(); } return $this->conn; } /** * Called via a callback when a message is received * Passes it back to the queuing system * * @param array $data Data * @return boolean */ public function handle_irc_message($data) { $this->plugin->enqueue_incoming_raw($data); return true; } /** * Called via a callback when NickServ responds to * the bots query asking if a nick is registered * * @param array $data Data * @return void */ public function handle_reg_response($data) { // Retrieve data $screenname = $data['screenname']; $nickdata = $this->regChecks[$screenname]; $usernick = $nickdata['user']->nickname; if (isset($this->regChecksLookup[$usernick])) { if ($data['registered']) { // Send message $this->plugin->send_confirmation_code($screenname, $nickdata['code'], $nickdata['user'], true); } else { $this->plugin->send_message($screenname, _m('Your nickname is not registered so IRC connectivity cannot be enabled')); $confirm = new Confirm_address(); $confirm->user_id = $user->id; $confirm->address_type = $this->plugin->transport; if ($confirm->find(true)) { $result = $confirm->delete(); if (!$result) { common_log_db_error($confirm, 'DELETE', __FILE__); // TRANS: Server error thrown on database error canceling IM address confirmation. $this->serverError(_('Couldn\'t delete confirmation.')); return; } } } // Unset lookup value unset($this->regChecksLookup[$usernick]); // Unset data unset($this->regChecks[$screename]); } } /** * Send a message using the daemon * * @param $data Message data * @return boolean true on success */ public function send_raw_message($data) { $this->connect(); if (!$this->conn) { return false; } if ($data['type'] != 'message') { // Nick checking $nickdata = $data['nickdata']; $usernick = $nickdata['user']->nickname; $screenname = $nickdata['screenname']; // Cancel any existing checks for this user if (isset($this->regChecksLookup[$usernick])) { unset($this->regChecks[$this->regChecksLookup[$usernick]]); } $this->regChecks[$screenname] = $nickdata; $this->regChecksLookup[$usernick] = $screenname; } try { $this->conn->send($data['data']['command'], $data['data']['args']); } catch (Phergie_Driver_Exception $e) { $this->conn->reconnect(); return false; } return true; } /** * Sends a ping * * @return void */ protected function sendPing() { $this->lastPing = time(); $this->conn->send('PING', $this->lastPing); } }