LiveChat – Jabber en nuestra aplicación web

Dado que la comunicaci�n bidireccional y la verificaci�n del estado de disponibilidad de un usuario en la red Jabber no es ya para nosotros ning�n problema, pong�monos manos a la obra y construyamos una aplicaci�n completa que permita a m�ltiples usuarios de Internet comunicarse con varios empleados (consultores). Hasta este momento hab�amos estudiado solamente el caso de un solo usuario que se comunica con un solo consultor, que es una situaci�n raramente encontrada en aplicaciones reales.

Nuestro plan de acci�n ser� el siguiente:

  • el cliente visualiza la p�gina con los contactos,
  • en la p�gina aparece la lista de los consultores disponibles en ese momento (est� claro que esta lista puede estar vac�a, en cuyo caso el cliente deber� esperar un momento),
  • si alguno de los consultores est� disponible, el cliente puede iniciar con �l una conversaci�n,
  • una vez iniciada la conversaci�n, el consultor desaparece de la lista de empleados disponibles y el cliente puede conversar sin interrupciones con la persona elegida.

El esquema de navegaci�n para las p�ginas web y la arquitectura de la aplicaci�n completa se muestran en la Figura 3.

Figura 3: Esquema de navegación y arquitectura de la aplicación

Como podemos ver, m�ltiples usuarios virtuales hacen uso de una misma cuenta en la red Jabber. Debido a esto, se hace necesario un mecanismo que permita redireccionar los mensajes enviados por el consultor a un usuario determinado.

.�El atributo thread

Como recordaremos, todo mensaje puede poseer el atributo opcional thread, que permite distribuir los mensajes enviados y recibidos en hilos l�gicos de conversaci�n sobre un tema dado. La especificaci�n del protocolo establece que un cliente Jabber, despu�s de haber recibido un mensaje con este atributo, deber�a:

  • a�adir a cada respuesta dada al mensaje el identificador del hilo de conversaci�n obtenido como valor del atributo,
  • ofrecer al usuario una interfaz que permita distinguir entre los diferentes hilos de conversaci�n, incluso cuando varios de ellos han sido realizados con el mismo usuario.

Pensemos un momento: si enviamos desde la p�gina web un comunicado que contenga el atributo thread, en cuyo valor se encuentre el identificador de la sesi�n PHP, las respuestas del consultor tambi�n contendr�n en su campo thread el identificador de sesi�n PHP. �Bingo! Esto nos permitir� diferenciar las preguntas hechas por diferentes usuarios de nuestro formulario a un mismo consultor.

Existe, desgraciadamente, un peque�o problema: Jabber es un protocolo bastante joven y no todas sus implementaciones est�n completamente conformes con la especificaci�n. En particular, en algunas soluciones el atributo thread es completamente ignorado, lo que evidentemente imposibilita el uso de la idea presentada m�s arriba. Sin embargo, no es cuesti�n de preocuparse demasiado por anticipado, puesto que tambi�n existen productos que implementan correctamente el protocolo, tales como Exodus, el cual ofrece todas las funciones est�ndar de un cliente de mensajer�a instant�nea, adem�s de una buena documentaci�n.

.�Estoy ocupado

El �ltimo problema que debemos resolver para que nuestra aplicaci�n sea una herramienta realmente �til es el de la asignaci�n de un usuario de la web (o sea, de su n�mero de sesi�n) a un consultor determinado. Para resolverlo, supondremos que la sesi�n se desarrollar� de la siguiente manera:

  • el consultor llega a su trabajo, arranca su cliente de mensajer�a instant�nea y cambia su estado de disponibilidad a chat, dando a saber de esta manera que est� listo para responder a las preguntas de los usuarios,
  • la informaci�n acerca de la disponibilidad del consultor se introduce en la base de datos de la aplicaci�n,
  • el usuario visita la p�gina web con la lista de consultores disponibles y selecciona uno de ellos para iniciar una conversaci�n,
  • en la base de datos de la aplicaci�n anotamos que el usuario de n�mero de sesi�n PHP tal se ha conectado con el consultor de identificador JID tal. Cambiamos el estado (en la base de datos) de este consultor a no disponible,
  • el consultor obtiene el primer mensaje del usuario web. Puesto que espera estar ocupado con esta conversaci�n por alg�n tiempo, cambia su estado de disponibilidad a �no molestar� (dnd),
  • ambas partes conversan sirvi�ndose cada una de su propia interfaz de usuario,
  • cada una de las partes puede finalizar la conversaci�n. Del lado del usuario, esto se realiza haciendo clic sobre un enlace determinado. El consultor debe cerrar la ventana en la que se ha llevado a cabo la conversaci�n (�muy importante!) y cambiar su estado de disponibilidad a chat,
  • cuando una de las partes pone fin a la conversaci�n, la entrada de la base de datos que se�alizaba la existencia de una relaci�n entre la sesi�n PHP y el JID es autom�ticamente eliminada.

Observemos ahora c�mo podemos poner este plan a la pr�ctica. El Listado 4 muestra la parte (modificada) de la aplicaci�n de consola, la cual hace uso repetido de dos clases: JabberConsultants y JabberMessages, cuyas definiciones pueden verse en los Listados 5 y 6 al final del art�culo.

Listado 4: Script lanzado desde la consola � console.php
<?php
/**
  * @package jabber.console
  */

require('lib/jabber/class.jabber.php');
require('inc/db.inc.php');

require('class/model/JabberConsultants.php');
require('class/model/JabberMessages.php');

$jmessages = new JabberMessages($db);
$jconsultants = new JabberConsultants($db);

$jconsultants->setAllUnavailableStatus();

$JABBER = new Jabber;

$JABBER->server         = 'localhost';
$JABBER->port           = '5222';
$JABBER->username       = 'www_send';
$JABBER->password       = 'www_send';
$JABBER->resource       = 'ClassJabberPHP';

print "Conect�ndose con el servidor $JABBER->server ...     ";
$JABBER->Connect() or die('�Ha sido imposible establecer la conexi�n!');
print "�la conexi�n ha sido correctamente establecida!\n";

print "Autorizando al usuario $JABBER->server ...     ";
$JABBER->SendAuth() or die('�No ha sido posible autorizar al usuario!');
print "�autorizaci�n correctamente realizada!\n";

print "Listo para enviar y recibir mensajes...\n";
$JABBER->SendPresence();

while(1) {
   $JABBER->CruiseControl(10);
   $msg_array = $jmessages->getMessagesForSend();

   foreach ($msg_array as $msg_to_send) {
      print "Enviando un mensaje a ".$msg_to_send['jid']."... \n";
      $JABBER->SendMessage($msg_to_send['jid'],"chat",NULL,
         array(
            "thread" => $msg_to_send['sid'],
            "body" => $msg_to_send['msg']
         )
      );

      $jmessages->markAsSend($msg_to_send['msg_id']);
   }
}

$JABBER->Disconnect();

function Handler_message_chat($message) {
   global $JABBER;

   $msg = $JABBER->GetInfoFromMessageBody($message);
   $sid = $JABBER->GetInfoFromMessageThread($message);

   if ($sid!='') {
      global $jmessages;
      $jmessages->sendMsgFromConsultant($sid,$msg);
   }
}

function Handler_presence_available($message) {
    global $JABBER;
    $jid =
       $JABBER->StripJID($JABBER->GetInfoFromPresenceFrom($message));
    $status = $JABBER->GetInfoFromPresenceShow($message);

    global $jconsultants;
    $jconsultants->setAvailableStatus($jid,1,$status);
}

function Handler_presence_unavailable($message) {
    global $JABBER;
    $jid =
       $JABBER->StripJID($JABBER->GetInfoFromPresenceFrom($message));

    global $jconsultants;
    $jconsultants->setAvailableStatus($jid,0,null);
}

?>

El proceso completo de comunicaci�n se muestra en la Figura 4.

Figura 4: Proceso de conversación con el consultor

Se hacen aqu� necesarias algunas aclaraciones acerca del c�digo presentado. No hemos hecho a�n menci�n del uso que hace �ste de ADOdb como su capa de abstracci�n para el acceso a la base de datos. Gracias a �sto no tenemos que preocuparnos por el problema de la dependencia de un tipo concreto de la base.

Notemos tambi�n la manera en que se env�an los mensajes nuevos: primero se introducen en la base de datos, y despu�s, con ayuda del script console.php, se transmiten a la red Jabber. Esta soluci�n tiene dos ventajas fundamentales: por un lado podemos conservar el historial de la comunicaci�n completa y, por el otro, el script console.php es el �nico (!) en toda la aplicaci�n que sabe de la existencia de la clase que implementa el protocolo Jabber. Esto hace sencilla la sustituci�n de esta clase por otra, o incluso, el uso de una red de mensajer�a instant�nea completamente diferente.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP