Hoy, a la hora del café, un amiguete me hablaba de fútbol, de mujeres y de cuánto le gustaría que Google Desktop pudiera indexar los mensajes de Gaim. Me dijo que, por lo visto, había existido antes un plugin (software cerrado) pero que se había muerto de asco al perder interés el autor y dejar de actualizarlo para gaim 1.x y superiores.
Yo le dije que me parecía bastante simple hacer uno, sin conocer a priori ni las tripas de Gaim ni las de Google Desktop (sabiendo, eso sí, que Gaim es extensible, que está portado a Windows, que hay un plugin que guarda logs, que para Google Desktop salen plugins como setas, etc.). Entonces --medio en broma, medio en serio-- el chaval me retó a escribir uno en los cuarenta minutos que nos quedaban.
Quedaría bien que dijera que lo conseguí pero me quedé algo corto de tiempo... Aunque no fue mi culpa O:-), sigue leyendo:
Para implementarlo escogí Python porque Gaim es extensible en ese lenguaje (con PyGaim) y además, en Windows, permite prototipado rápido cuando hay COM de por medio, caso de GDS. Podría haber usado también Perl pero Python (ActivePython) ya estaba instalado en la máquina y además los módulos win32 y yo nos conocíamos de antes.
Después de echar un vistazo rápido tanto al API de Gaim como al API de indexación de GDS, estaba perfactamente seguro que podía escribirlo quince minutos y que me sobrarían cinco :-)
Por desgracia las cosas se torcieron con PyGaim. La interfaz que exporta se supone que es un calco de la de la interfaz C (ha sido generada con SWIG) pero es falso: el prototipo de algunas señales ha cambiado (las del API Conversation en particular) y son cambios gordos:
En la señal received-im-msg y sent-im-msg (generadas en Gaim cuando el usuario manda/recibe un mensaje) no se propaga la conversación (GaimConversation), sólo la cuenta que estás utilizando, el nombre del usuario con el que hablas y el mensaje. Sin la información de GaimConversation, es difícil meter todos los mensajes y respuestas dentro de un contexto, así como llevar un control con marcas de tiempo.
Tras darle bastantes vueltas y pasarme del tiempo, al final tiré la toalla e hice una chapuza: todos los timestamps se calculan independientementes de gaim (con gmtime) y el contexto (el "conversation_id", un entero que pide GDS) se establece a partir de un hash del nombre de nuestro interlocutor, así que todas las conversaciones que tengamos con él --sean del tema que sean-- aparecerán agrupadas juntas en GDS.
Al final escribí el bicho en casi una hora. Considerando que empecé sin saber nada de Gaim ni de Google Desktop os podéis hacer una idea de lo fácil que es extender ese par, si bien PyGaim está un poco en pañales.
No sé si PyGaim 2.0 (para el futuro Gaim 2.0) arregla esos problemas pero aviso que para extender Gaim parece mejor opción Perl y Tcl.
El plugin ha sido escrito y testeado (poco o nada X-D) para Gaim 1.5.0 (PyGaim 1.5.0-1) y Google Desktop 2.0. Es feo, sucio y despreciable: así que si tenéis alguna sugerencia (especialmente en lo del "conversation_id" o veis algún bug no dudéis en decirlo.
# -*- coding: UTF-8 -*-
import sha
import time
import pywintypes
import pythoncom
import win32com.client
import gaim
_NAME = "GaimDS"
_VERSION = "0.1"
_DESCRIPTION = "Indexa conversaciones en GDS"
# TODO: no hay entrada en el registro de Gaim
_GAIM_PATH = "C:\\Archivos de programa\\Gaim\\gaim.exe"
PLUGIN_INFO = {
'python_api_version' : 2,
'name' : _NAME,
'version' : _VERSION,
'summary' : _DESCRIPTION,
'description' : _DESCRIPTION,
'author' : "Jorge Rodríguez <jorginius@gmail.com>",
'url' : "http://libertonia.escomposlinux.org/user/jorginius/Diary",
'load' : "gds_load",
'unload' : "gds_unload"
}
_EVENT_FACTORY = None
_GUID = '{10a51bce-6670-65da-f0c0-40a8060c107f}'
def register_im_cb(nil, account, buddy, msg, flags):
event = self.event_factory.CreateEvent(_GUID, "Google.Desktop.IM")
username = gaim.gaim_account_get_username(account)
event.AddProperty("format", "text/html")
event.AddProperty("content", "%s: %s" % (username, buddy))
event.AddProperty("user_name", username)
event.AddProperty("buddy_name", buddy)
event.AddProperty("message_time", pywintypes.Time(time.gmtime()))
event.AddProperty("conversation_id",
int(sha.sha(buddy).hexdigest()[12:28], 16))
event.Sent()
def gds_load(plugin):
try:
obj = win32com.client.Dispatch("GoogleDesktopSearch.Register")
obj.RegisterComponent(_GUID,
["Title", _NAME,
"Description", _DESCRIPTION,
"Icon", _GAIM_PATH + ",1"])
_EVENT_FACTORY = win32com.client.Dispatch (
"GoogleDesktopSearch.EventFactory")
except: pass
handle = gaim.gaim_conversations_get_handle()
gaim.gaim_python_signal_connect(plugin,
handle,
"sent-im-msg",
register_im_cb,
None)
gaim.gaim_python_signal_connect(plugin,
handle,
"received-im-msg",
register_im_cb,
None)
def gds_unload(plugin): pass
¿Alguno ha escrito otros plugins para Google Desktop? y, por añadir algo más de chicha: ¿qué pensáis de Google Desktop?.
He visto que jamarier y man ls se preguntan sobre alternativas a WinFS en "El parto de la burra..." (de la historia ¿Vista con dioptrías?). A nivel práctico, no debería haber mucha diferencia entre el futuro WinFS y el actualísimo Google Desktop, Spotlight o Beagle, por muy a nivel de aplicación que sean esos tres últimos.