Está en la página 1de 5

DESARROLLO Python

EXTENDIENDO XCHAT
Por qu escribir comandos de IRC cuando Python puede hacerlo por nosotros?

Los fanticos del IRC encuentran pesado tener que escribir ciertas combinaciones de comandos cada vez que entran en un servidor. Pero XChat nos echa una mano mediante los scripts Python. POR JOS MARA RUIZ
Chat (ver Recurso [1]) es uno de los ms famosos clientes de mensajera IRC existentes. Es simple, grfico y extensible. Y es esta ltima cualidad la que vamos a explotar gracias a Python. XChat soporta plugins en varios lenguajes de programacin con los que nos podemos ahorrar muchos tecleos innecesarios. Vamos a automatizar la ejecucin de ciertos comandos. Para comenzar es imprescindible que nuestra versin de XChat soporte mdulos Python (documentacin de referencia en Recurso [2]). En este artculo estoy empleando la versin 2.6.4, pero cualquiera superior a la 2.6.0 ser parecida. Durante el arranque de XChat podemos ver si soporta mdulos Python si aparece:
Python interface loaded __module_name__ =U Hola Mundo __module_version__ = 1.1 __module_description__ =U Ejemplo de mdulo Python import xchat xchat.command(msg %s %s %U (#python-es,Hola a todos))

__module_name__ =U Hola Mundo __module_version__ = 1.0 __module_description__ =U Ejemplo de mdulo Python print Hola Mundo!

Este es nuestro primer mdulo, y como todo ejemplo simple, hace ms bien poco. Bsicamente muestra en la ventana de XChat la frase Hola Mundo! (ver Figura 1). Lo peor de todo es que ni siquiera manda esta frase como mensaje, sino que slo aparece en nuestra ventana local como se puede apreciar en la Figura 1. Para cargarlo tenemos que ejecutar en la linea de comandos de XChat:
/load /home/josemaria/p.py

Para poder escribir un mensaje a un canal tenemos que emplear un comando de IRC, el comando msg que acepta dos parmetros, el canal y el texto a escribir. Para poder enviar comandos a XChat necesitamos usar la librera xchat que incorpora las funciones necesarias para interactuar con XChat. Pero este cdigo no es muy polivalente, puesto que hemos puesto en una

Pasemos a la accin con un par de ejemplos rpidos antes de enumerar las funciones de las que dispondremos:

Hola mundo
Comenzaremos con el infame Hola mundo que a todos gusta:

Hay que especificar la ruta, por eso aconsejo poner los plugins en el directorio personal, as podrn cargarse usando /load ejemplo.py. Es importante que los ficheros acaben en .py, en caso contrario XChat no sabr cmo manejarlos. Prosigamos a algo ms til para que podamos mandar un mensaje a un canal:

Figura 1: Probamos nuestro plugin Hola Mundo.

50

Nmero 19

WWW.LINUX- MAGAZINE.ES

Python DESARROLLO

cadena el canal en el que nos encontramos. Necesitamos algo ms dinmico, de manera que podamos ejecutar la funcin en un canal cualquiera y funcione:
__module_name__ =U Hola Mundo __module_version__ = 1.2 __module_description__ =U Ejemplo de mdulo Python import xchat chan = xchat.get_info(channel) xchat.command(msg %s %s %U (chan,Hola a todos))

slo la veramos nosotros, es decir, slo sirve para dar informacin de forma local. xchat.emit_print() imprimir el mensaje cuando se genere el evento que le digamos. xchat.prnt() tiene ese nombre tan peculiar debido a que la funcin print() es especial en Python y no podemos definir otra que se llame igual. Los eventos posibles se pueden ver en XChat pulsando en la barra de men en la opcin Configuracin> Avanzado > Textos de eventos. El nombre de evento debe ponerse entre puesto que Python espera una cadena de texto. Ejemplos de eventos seran: Join, alguien entra en el canal Channel Message, alguien escribe en el canal Kick, se ha echado (de una patada) a alguien de un canal

Figura 2: El mdulo prueba.py escribe la cadena en la ventana de X-Chat.

Ahora se coge el nombre del canal con la funcin get_info() y lo empleamos para mandar el mensaje. get_info devuelve la informacin del canal donde hayamos cargado la funcin. En la Figura 2 se puede ver el resultado. Vamos a ver unas descripciones de las funciones que podremos usar en el desarrollo de nuestros scripts.

una funcin para algo que podemos hacer con comparacin de cadenas de caracteres? Porque resulta que es necesario realizar la comparacin segn el RFC1459, el estndar donde se define el protocolo de IRC.

Funciones que devuelven informacin


Existen 3 funciones que nos permiten extraer informacin de XChat. Con esta informacin podremos tomar decisiones, por ejemplo, si podemos usar ciertas caractersticas de XChat que slo estn presentes en sus ltimas versiones. xchat.get_info(type) permite obtener una serie de datos sobre la sesin actual de XChat, como pueden ser: away mensaje de away channel canal en el contexto actual host hostname del servidor al que ests conectado network nombre de la red de servidores, en caso contrario none nick tu nick actual server Nombre del servidor al que ests conectado o None si no lo ests topic topic del canal actual version versin de Xchat xchatdir directorio de configuracin de XChat (por ejemplo /home/josemaria/.xchat2)

xchat.command(cadena) ejecuta el comando que le pasemos. Con esta funcin ya podemos escribir en un canal, empleando el comando IRC para ello. Hay dos maneras: xchat.command(msg %s %s % (canal, mensaje)) xchat.command(say %s % (mensaje))

Funciones genricas
Comencemos con las funciones ms simples. En la documentacin se les denomina funciones genricas, debido a que no tienen un uso predefinido o especial. Las dos primeras son xchat.prnt(cadena) y xchat.emit_print(nombre_evento, *argumentos). Ambas nos permiten escribir en la ventana de XChat, pero no enviar un mensaje al canal. Esta informacin

El primer comando escribe el mensaje en el canal que le digamos, mientras que el segundo comando lo hace en el que est activo en ese momento. Por ltimo, la funcin xchat.nickcmp(s1,s2) nos permite comparar nicks y nombres de canales. Parece extrao porque para qu necesitamos

Listado 1: Algunos Datos de XChat


01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 __module_name__ = Datos del canal __module_version__ = 1.0 __module_description__ = Ejemplo de mdulo Python import xchat print ======================================== print print Lista de usuarios: print usuarios = xchat.get_list(users) for usuario in usuarios: print usuario.nick print print Temtica de el canal: +xchat.get_info(topic) print print ========================================

xchat.get_prefs(nombre-preferencia) permite obtener los valores que normalmente puedes ajustar con /set. Estos valores son exclusivos de XChat, y van desde los colores que se estn usando hasta el tipo de fuente que se ha configurado. Mientras que xchat.get_list(tipo) nos permite obtener listas de datos sobre los siguientes objetos: channels canales dcc conexiones dcc users usuarios ignore usuarios ignorados

WWW.LINUX- MAGAZINE.ES

Nmero 19

51

DESARROLLO Python

Listado 2: Nuestro Recordador.


01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 version = 1.0 __module_name__ = Saludos __module_version__ = versin __module_description__ = Mdulo de XChat para recordar cosas __module_author__ = Jos Mara Ruiz Aguilera import xchat # Variable global para almacenar el enganche y poder controlarlo enganche = None # si quedan menos de 10 minutos para las 00 se queja cada 5 segundos def parar_cb(word, word_eol, userdata): global enganche if enganche is not None: xchat.unhook(enganche) enganche = None print Recordador desactivado! def timeout_cb(userdata): print userdata return 1 # El 1 hace que siga ejecutndose

/comando NICK josemaria word[0] = comando word[1] = NICK word[2] = jose maria

Mientras que word_eol guarda toda la cadena, desde el parmetro en cuestin hasta el final:
/comando NICK josemaria word_eol[0] = comando NICKU josemaria word_eol[1] = NICK josemaria word_eol[2] = josemaria

Sinceramente no logro entender la utilidad de word_eol, def arranca(word, word_eol,userdata): pero es obligatorio global enganche esperarlo en nuestra # arrancamos el contador de tiempo, multiplicando los segundos por 1000 funcin, por lo que # deberamos controlar los parmetros pero por falta de espacio no es tendr que ir en la # posible cabecera de la enganche = xchat.hook_timer(int(word[1])*1000, timeout_cb,userdata=word[2]) misma. userdata es un parmetro que xchat.hook_command(ARRANCA,arranca,help=/arranca <segundos> <mensaje>) puede contener valoxchat.hook_command(PARA, parar_cb) res que nosotros mismos pasemos a xchat.prnt(Mdulo Recordado) la funcin de callxchat.prnt(Puedes hacer que te recuerde algo cada cierta cantidad de segundos) back. Veamos un ejemplo de las funciones que prioridades, y una vez que una Toda callback debe devolver un valor recogen informacin: un script que nos funcin se ejecuta, puede decidir de cuatro posibles. Es aqu donde se lista los usuarios presentes as como el impedir que se sigan ejecutando las decide si dejaremos que se sigan ejecutopic, temtica, del canal. El cdigo de menor prioridad, lo que nos da tando las callbacks que queden en la aparece en el Listado 1 y el resultado es mucho juego. lista si las hubiese: el que aparece en la Figura 3. Pero antes de comenzar con las EAT_PLUGIN, no permitimos que funciones de XChat para gestionar ningn otro plugin reciba este evento Funciones de enganche eventos debemos comprender los EAT_XCHAT, no permitimos que Uno de los puntos fuertes de emplear parmetros que recibirn nuestras XChat dispare sus propias funciones scripts es que XChat posee un sistema de funciones de callback. con este evento eventos. Cada evento posee una lista de Una funcin de callback recibe en EAT_ALL, no permitimos que nadie funciones, tambin llamadas callbacks, XChat tres parmetros: ms use este evento (ni otras callbacks dentro de nuestro mdulo) a las que se debe llamar si el evento word EAT_NONE, dejar que todo ocurra de acontece. Podemos insertar nuestras pro word_eol forma normal pias funciones dentro de esa lista, y userdata Puede haber varios mdulos esperando adems tendremos algo de control sobre en qu punto de la lista sern insertadas. La lista que se asigna a cada evento est ordenada por El parmetro word es una lista con cada parmetro que acompae al comando: este evento, y cada mdulo tener varias callbacks esperndolo. Con el valor de salida de la funcin de callback

52

Nmero 19

WWW.LINUX- MAGAZINE.ES

DESARROLLO Python

controlamos qu ocurrir despus de que procesemos este evento. Ahora ya estamos listos para ver las funciones que asignan las callbacks.

Funciones de enganche
xchat.hook_command(nombre, callback, userdata=None, priority=PRI_NORM, help=None) nos permite asignar un comando a una callback. Imaginemos que queremos automatizar una accin, digamos autoinvitarnos a un canal y entrar en l, entonces tendramos que usar el siguiente cdigo:
01 __module_name__ = Autoinvitado 02 __module_version__ = 0.1 03 __module_description__ = Ejecutamos dos comandos 04 import xchat 05 06 def autoinvita (word, word_eol,userdata): 07 xchat.command(chanserv invite #micanal) 08 xchat.command(join #micanal) 09 return None 10 11 xchat.hook_command(entra, autoinvita, help=/entra)

del servidor, como pueden ser PRIMSG, NOTICE, o PART. xchat.hook_timer(timeout, callback, userdata=None) te puede granjear muchos enemigos, puesto que sirve para ejecutar una callback cada cierta cantidad de milisegundos. Puede hacer que cada 10 segundos digas algo gracioso o no demasiado acertado. La decisin es personal. Yo personalmente uso este tipo de enganche para generar mensajes y por tanto probar el resto de callbacks que se disparan cuando algo se imprime. xchat.hook_unload(timeout, callback, userdata=None) se dispara cuando se descarga un plugin, se puede usar para imprimir por pantalla su descarga o hacer tareas de limpieza. Y por ltimo xchat.unhook(handler) elimina la funcin reflejada por handler que se registr con anterioridad. Todas las funciones hook_ devuelven un handler, as que es posible guardarlo en una variable para posteriormente desactivarlo.

Figura 4: El mdulo Recordador nos imprime un recordatorio cada cierto tiempo en la ventana del canal.

Gestin de contexto
El ltimo grupo de funciones son las encargadas de gestionar lo contextos. XChat posee pestaas, y las pestaas contienen una conversacin en un canal o privada dentro de un servidor. A esta informacin se le denomina contexto en el argot de XChat. Por el momento hemos estado usando el contexto xchat que engloba a toda la aplicacin. xchat.get_context() nos devuelve el contexto actual y xchat.find_context(server=None, channel=None) localiza el contexto que pertenece al servidor y canal que le especificamos. Una vez tengamos el contexto necesario podemos hacer uso de sus funciones, como pueden ser micontexto.prnt() o micontexto.command().

Despus de cargar el script slo tendramos que usar el comando /entra y se ejecutara la funcin autoinvita. xchat.hook_print(name, callback, userdata=None, priority=PRI_NORM) permite capturar eventos de impresin, cualquier cosa que se imprima en XChat. Mientras que xchat.hook_server(name, callback, userdata=None, priority=PRI_NORM) captura eventos

hablas con otras personas usando XChat se te olvidan las cosas. He creado un script que hace uso de algunos de los conceptos explicados. Su misin es permitir al usuario mostrar por pantalla un mensaje usando intervalos en segundos. El usuario podr activar y desactivar los mensajes. Para ello he creado dos comandos /arranca segundos mensaje y /para. Arranca activa un enganche que se dispara segn la cantidad de segundos especificada. Con para podemos parar la aparicin del mensaje en cualquier momento. Todo el cdigo est en el Listado 2 y en la Figura 4 podemos ver el resultado. Qu podemos hacer para que cargue cada vez que lo haga XChat? Es tan simple como poner el fichero que contenga nuestro script dentro del directorio ~/.xchat2. Cuando XChat arranca comprueba ese directorio en busca de script para ejecutar.

Conclusin
El interfaz de XChat puede resultar algo complicado de entender, pero una vez se hayan visto unos cuantos ejemplos no es tan complicado de manejar. Quiz lo que ms puede dificultar nuestra tarea es la escasa documentacin, as como el reducido nmero de ejemplos que podemos encontrar en Internet. An con todo esto, es una ayuda imprescindible para aquellos que pasamos muchas horas en canales de IRC. Ya no hay excusa para automatizar esas combinaciones de comandos tan I complicados a veces.

Creemos un plugin
Ahora que disponemos de todas las herramientas necesarias para comunicarnos con XChat, podemos crear algo til. Digamos que eres una persona despistada, como lo es el autor del artculo, y mientras

RECURSOS
[1] http://www.xchat.org [2] http://labix.org/xchat-python

Figura 3: El mdulo Datos del canal imprime los usuarios y la temtica del canal.

54

Nmero 19

WWW.LINUX- MAGAZINE.ES

También podría gustarte