TransBot

Suite à l’article sur Twisted, framework réseau, une autre application des Bots XMPP : un client MUC permettant de traduire les messages.

L’origine de ce Bot était de pourvoir discuter par Chat XMPP avec mes cousines d’espagne sans être limité par le barrière de la langue.

Apertium

Il existe de nombreux outils de traduction, mais Apertium, développé initialement par l’Université d’Alicante, me semblait le plus adapté à une traduction Français / Espagnol, et qui plus est il est sous license GPL ;)

P.I. ce logiciel s’installe très facilement sous Debian/Ubuntu via un classique apt-get install apertium-fr-es.

P.S. le dépot d’Ubuntu n’est pas à jour, il faut passer par un PPA :

$ wget http://apertium.projectjj.com/apt/install-nightly.sh
$ sudo bash ./install-nightly.sh
$ sudo aptitude update  # the script above did this, but…
$ sudo aptitude install apertium-en-es apertium-fr-es apertium
$ echo “Eso es un test” | apertium es-en
This is a test

MUC Bot XMPP

Nous allons créer notre classe MUCTranslateBot comme sous classe de MUCClient, et non comme un sous-protocole de MUCClientProtocol , de manière à pouvoir surcharger la méthode receivedGroupChat.
En effet, MUCClient implémente receivedGroupChat qui fait la distinction entre les messages mettant à jour le sujet de la salle de discussion, les messages d’historique et les messages ’lives’. Dans notre cas on ne prendra en compte que les messages ’lives’.

# transbot.py

from twisted.python import log
from twisted.words.protocols.jabber.jid import JID
from wokkel.client import XMPPClient
from wokkel.muc import MUCClient

from subprocess import check_output

class MUCTranslateBot(MUCClient):
   """I join a room and respond to translation requests."""

   def __init__(self, roomJID, nick):
       MUCClient.__init__(self)
       self.roomJID = roomJID
       self.nick = nick

   def connectionInitialized(self):
       """Once authorized, join the room.

       If the join action causes a new room to be created, the room will be
       locked until configured. Here we will just accept the default
       configuration by submitting an empty form using configure, which
       usually results in a public non-persistent room."""

       def joinedRoom(room):
           if room.locked:
               # Just accept the default configuration.
               return self.configure(room.roomJID, {})

       MUCClient.connectionInitialized(self)

       d = self.join(self.roomJID, self.nick)
       d.addCallback(joinedRoom)
       d.addCallback(lambda _: log.msg("Joined room"))
       d.addErrback(log.err, "Join failed")

   def receivedGroupChat(self, room, user, message):
       """Called when a groupchat message was received.

       Check if the message was addressed to my nick. Respond by sending
       translated message to the room addressed to the sender."""

       if message.body.startswith(u"fr-es:"):
           nick, text = message.body.split(':', 1)
           text = text.strip().lower()

           # Call apertium to translate messages
           output = check_output("echo '%s' | apertium fr-es" % text, shell=True)
           output = unicode(output, "utf-8")  # convert output to unicode

           self.groupChat(self.roomJID, u"es: %s" % output)

       elif message.body.startswith(u"es-fr:"):
           nick, text = message.body.split(':', 1)
           text = text.strip().lower()

           # Call apertium to translate messages
           output = check_output("echo '%s' | apertium es-fr" % text, shell=True)
           output = unicode(output, "utf-8")  # convert output to unicode

           self.groupChat(self.roomJID, u"fr: %s" % output)

Notre Bot est maintenant complet, il ne nous manque plus que le fichier de configuration pour le lanceur twistd :

Application

# transbot.tac

from twisted.application import service
from twisted.words.protocols.jabber.jid import JID
from wokkel.client import XMPPClient

from transbot import MUCTranslateBot

application = service.Application("TransBot")

xmppclient = XMPPClient(JID("user@jabber.fr/transbot"), "pass")
xmppclient.logTraffic = True
xmppclient.setServiceParent(application)

transbot = MUCTranslateBot(JID("trans@chat.jabberfr.org"), u"transbot")
transbot.setHandlerParent(xmppclient)

Il ne reste plus qu’a lancer notre Bot via : twisted -y transbot.tac
- il se connectera et/ou créera la salle de discussion trans@chat.jabberfr.org
- et attendra des messages du type :

  • fr-es: Bonjour tout le monde ! Comment allez-vous ?
  • pour répondre : transbot: es: saludo todo el mondo ! cómo íos ?