Your continued donations keep Swissjabber running!

Python Bot

Aus Swissjabber

Wechseln zu: Navigation, Suche

Es kann sehr praktisch sein, einen eigenen Bot zu haben. Dieser kann die unterschiedlichsten Anforderungen und Wünsche erfüllen. Mit python-jabberbot steht ein Framework zur Verfügung, welche die Erstellung von Jabber-Bots auch für weniger erfahrene Benutzer möglich macht.

Inhaltsverzeichnis

Einrichtung

python-jabberbot muss installiert sein. Seine Abhängigkeit ist python-xmpp, dieses Paket ist wahrscheinlich auf allen gängigen Distributionen im Paketmanagement-System verfügbar. Unter Debian und Fedora sind fertige Pakete vorhanden. Auf allen anderen Linux-Plattformen muss es gemäss Dokumentation installiert werden.

Unter Debian

apt-get install python-jabberbot

Unter Fedora

yum -y install python-jabberbot

Erster Bot

Der erste Bot kann auf einen Befehl eine Antwort geben. Nichts weltbewegendes, aber ein nettes Beispiel zur Funktionsdemonstration. Der erste Schritt ist der Import der benötigten Module.

from jabberbot import JabberBot, botcmd

Im ersten Abschnitt wird der allgemeine Teil des Bot definiert. Der Klasse-Namen kann frei gewählt werden. Der Beschreibungsteil wird von python-jabberbot dazu benutzt, beim Aufrufen der Hilfe Informationen über den Bot preiszugeben. Die Funktion des Bot und auch einen Kontakt-Adresse sollte als Minimum definiert werden (siehe auch Bot).

class pyBot(JabberBot):
    """
    This is a simple Jabber bot.  It can give you an answer.
    
    Contact: Du <du at irgendeinedomain.ch>
    """

Die Befehle werden nach der Zeile @botcmd, die als Dekorator dient, definiert. Mit @botcmd(hidden=True) können Befehle von der Anzeige durch help ausgeschlossen werden. Der Aufbau ist immer gleich: def einBefehl( self, mess, args): , ein Kommentar, welcher auch bei der Eingabe von help verarbeitet wird und danach, was zu tun ist. return gibt die Ausgabe dann an den Benutzer zurück.

@botcmd
def hello( self, mess, args):
    """Say hello"""
    return 'Hello Fabian, I am your python jabber bot.'

Die Anmelde-Daten bestehen aus einem Jabber-Konto und den Passwort. Der Klasse-Name aus dem ersten Abschnitt muss hier benutzt werden.

bot = pyBot('fabian.a@swissjabber.ch','xxxx')

Zuletzt muss dem Bot gesagt werde, dass er immer laufen soll.

bot.serve_forever()

Der komplette Code kann unter pybot01.py gefunden werden. Ein weiteres Beispiel für einen ersten Bot ist das Erzeugen von Echos. Die eingegebene Nachricht wird wieder zurückgeschickt.

@botcmd
def echo( self, mess, args):
    """I am your echo"""
    return args

Verwendung

Im entsprechenden Verzeichnis kann nun der Bot gestartet werden.

python pybot01.py
[fab@localhost Documents]$ python pybot01.py 
/usr/lib/python2.6/site-packages/xmpp/auth.py:24: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
  import sha,base64,random,dispatcher,re
/usr/lib/python2.6/site-packages/xmpp/auth.py:26: DeprecationWarning: the md5 module is deprecated; use hashlib instead
  import md5
/usr/lib/python2.6/site-packages/xmpp/transports.py:315: DeprecationWarning: socket.ssl() is deprecated.  Use ssl.wrap_socket() instead.
  tcpsock._sslObj    = socket.ssl(tcpsock._sock, None, None)
pyBot : *** roster ***
pyBot :   admin-bot@swissjabber.ch
pyBot :   whois@swissjabber.ch
pyBot :   fabian.a@swissjabber.ch
pyBot : *** roster ***
pyBot : bot connected. serving forever.

Die Fehlermeldungen sind etwas unschön, stören den Betrieb aber nicht. Wenn der Roster angezeigt wird und der der Bot verbunden ist, ist er bereit und wartet auf Befehle. Falls sich der Bot nicht verbinden kann, sollte die Konto-Daten geprüft werden.

pyBot : unable to authorize with server.
pyBot : could not connect to server - aborting.

Der Hilfe-Befehl gibt Bot-Daten und die vorhandenen Befehle aus.

help

Datei:Pybot01.png

Der einzige Befehl, der vorhanden ist, ist hello.

hello

Datei:Pybot02.png

Wird ein unbekannter Befehl eingegeben, verarbeitet das Jabberbot-Framework die Eingabe, respektive gibt eine entsprechende Meldung aus.

Datei:Pybot03.png

Beenden

Der Bot kann mit Ctrl + c beendet werden, wenn er nicht mehr gebraucht wird.

Nachrichten-Verarbeitung

Das Jabberbot-Framework kann Nachrichten-Teile, wie den Absender und den Nachrichttext, direkt ansprechen. Die Daten müssen nicht zuerst extraiert werden. get.Body() gibt den Nachrichtentext zurück

@botcmd
def messagebody( self, mess, args):
    """Displays the message body"""
    return mess.getBody()

Der Absender kann mit get.From() identifiziert werden. In diesen Beispielen gibt dies den eigenen Benutzer-Namen zurück.

@botcmd
def sender( self, mess, args):
    """Displays the sender of the message"""
    return mess.getFrom()

Zum Bestimmen des Nachrichten-Type kann get.Type() benutzt werden.

@botcmd
def messagetype( self, mess, args):
    """Displays the type of the message"""
    return mess.getType()

Bestimmen der Eigenschaften kann mit getProperties() gemacht werden.

@botcmd
def properties( self, mess, args):
    """Displays the properties of the message"""
    return mess.getProperties()

System-Befehle

Zitate

Mit fortune lassen sich auf der Kommandozeile Zitate anzeigen. Diese lassen sich auch an einen Klient schicken. Natürlich muss fortune installiert sein, eventuell ist der Pfad anzupassen.

Zusätzlich zu den oben angegebenen Daten muss das os-Modul importiert werden.

import os

Der Code setzt sich aus dem Aufruf von fortune als System-Befehl und dem Zitat als Rückgabewert zusammen.

@botcmd
def fortune( self, mess, args):
    """Get a random quote"""
    fortune = os.popen('/usr/bin/fortune').read()
    return fortune

Jeder Aufruf gibt ein neues Zitat zurück. Der komplette Source-Code befindet sich hier.

Eingeloggte Benutzer

Statt eine SSH-Verbindung zum Server herzustellen, kann auch Jabber benutzt werden, um zu sehen, wer eingelogt ist.

Der Code führt who als System-Befehl aus. Der Unterschied zu fortune ist minimal. Nach dieser Konstruktion lassen sich weitere Befehle integrieren.

@botcmd
def who(self, mess, args):
    """Display who's currently logged in"""
    who = os.popen('/usr/bin/who').read().strip()
    return who

Der Aufruf gibt eine Liste zurück.

fab      tty1         2009-12-11 20:54 (:0)
fab      pts/0        2009-12-12 21:16 (:0.0)
fab      pts/1        2009-12-12 21:56 (:0.0)
fab      pts/2        2009-12-12 23:59 (:0.0)
fab      pts/3        2009-12-13 09:15 (:0.0)

Der komplette Source-Code dieses Beispiels kann hier gefunden werden.

Zeit

Durch das Senden von time an den Bot, wird die aktuelle Zeit der Maschine, auf welcher der Bot läuft, übertragen. Damit mit Zeitangaben gearbeitet werden kann, muss das datetime-Modul importiert werden.

import datetime

Je nach persönlichem Geschmack kann das Ausgabe-Format angepasst werden.

@botcmd
def time( self, mess, args):
   """Displays current server time"""
   return datetime.datetime.today().strftime('%A, %d. %B %Y %H:%M:%S')

Die Antwort des Bot ist die formatierte Datum/Zeit-Angabe.

Sunday, 13. December 2009 00:52:29 

Oder das Beispiel aus der Dokumentation von python-jabberbot.

@botcmd
def time( self, mess, args):
    """Displays current server time"""
    return str(datetime.datetime.now())

Der Source-Code pytimebot.py dieses Beispiels.

Whois

Möchten nun Befehle ausgeführt werden, welche ein Argument erfordern, funktioniert es mit dem bisherigen Beispielen nicht. Das Argument ist args und muss analog dem Aufruf auf der Kommanozeile bei der Ausführung mitgegeben werden.

@botcmd
def whois( self, mess, args):
    """Displays details about a domain name or an IP address"""
    whois = os.popen('/usr/bin/whois ' + args).read().strip()
    return whois

Wird die Zeile

whois = os.popen('/usr/bin/whois ' + args).read().strip()

durch

whois = os.popen('/usr/bin/nslookup ' + args).read().strip()

ersetzt oder als separater Befehl eingefügt, lassen sich weitere Informationen gewinnen. Natürlich dann auch eine Kombination erfolgen.

@botcmd
def whois( self, mess, args):
    """Displays details about a domain name or an IP address"""
    whois = os.popen('/usr/bin/whois ' + args).read().strip()
    nslook = os.popen('/usr/bin/nslookup ' + args).read().strip()
    return 'Whois\n--------\n%s\n\nNslookup\n--------------\n%s' % ( whois, nslook, )

Eine ähnliche Funktion stellt der Whois-Bot bereit. Der Source-Code zu diesem Beispiel befindet sich hier.

System-Informationen

Für Benutzer kann es interessant, mehr über das System zu erfahren, auf welchem der Bot läuft.Das os-Modul importiert sein.

@botcmd
def server(self, mess, args):
    """Displays server information"""
    server = os.uname()
    data = "System: \t" + server[0] + \
        "\n" +"FQDN: \t" + server[1] + \
        "\n" +"Kernel: \t" + server[2] + \
        "\n" +"Data: \t" + server[3] + \
        "\n" +"Arch: \t" + server[4]
    return data

Die Ausgabe ist dann als Liste formatiert.

System: 	Linux
FQDN: 	        localhost.localdomain
Kernel: 	2.6.31.6-162.fc12.i686
Data: 	        #1 SMP Fri Dec 4 01:09:09 EST 2009
Arch: 	        i686

Der Source-Code zu diesem Beispiel befindet sich hier. Ein alternatives Beispiel kann im Beispiel-Code des Jabberbot-Framework gefunden werden.

Uptime

Interessiert, wie lange das System, auf welchem der Bot ausgeführt wird, schon läuft? Dann ist dieser Code-Block das Richtige. Grosse Teile dieses Codes sind an die Arbeit von Hubert Chathi und seinem System status bot angelehnt und abgeschaut.

@botcmd
def uptime(self, mess, args):
    """Displays the server uptime"""
    uptime = open('/proc/uptime').read().split()[0]
    # This is heavily based on the work of Hubert Chathi and his System status bot.
    uptime = float(uptime)
    (uptime,secs) = (int(uptime / 60), uptime % 60)
    (uptime,mins) = divmod(uptime,60)
    (days,hours) = divmod(uptime,24)

    uptime = 'Uptime: %d day%s, %d hour%s %02d min%s' % (days, days != 1 and 's' or '', hours, hours != 1 and 's' or '', mins, mins != 1 and 's' or '')
    return uptime

Die Ausgabe sieht dann wie folgt aus:

Uptime: 1 day, 19 hours 24 mins

Der Source-Code kann hier gefunden werden.

Umfangreichere Ausgabe

Bei der Eingabe von help wird, wie bereits erwähnt, eine Liste mit den verfügbaren Befehlen an den Client geschickt. Es stehen zwei Blöcke zur Verfügung, um die Ausgabe statisch zu erweitern.

    def top_of_help_message(self):
        """Returns a string that forms the top of the help message"""
        return "pyBot - just a simple Bot"
    def bottom_of_help_message(self):
        """Returns a string that forms the bottom of the help message"""
        return "Version: 0.0.1"

Die Ausgabe der neuen Kopf- und Fusszeile:

pyBot - just a simple Bot

This is a simple Jabber bot.  It can give you an answer.
    
    Contact: Fabian Affolter <fabian at bernewireless.net>

hello: Say hello

Version: 0.0.1

Trennen von Konfiguration und Code

Sobald der Bot auch anderen Benutzern zur Verfügung stehen soll, tritt ein Problem auf. Der Benutzername und das Passwort sind bis jetzt im Code integriert. Damit es die Benutzer einfacher haben, sollten die Anmeldedaten in eine separate Datei ausgelagert werden. Als erstes Beispiel heisst die Datei mein-pybot und befindet sich im gleichen Verzeichnis wie der Bot. Als Inhalt muss sie folgende Daten enthalten:

[pybot]
username = fabian.a@swissjabber.ch
password = xxxx

Für das Einlesen von Daten steht ein Python-Modul (ConfigParser) zur Verfügung.

import ConfigParser

In config.read wird der Dateiname angegeben.

config = ConfigParser.RawConfigParser()
config.read(['mein-pybot','mein-pybot'])

Die Daten müssen dann anstelle der Anmeldedaten eingefügt werden. Zuerst wird der Abschnitt (pybot) definiert und danach der Wert (username oder password).

bot = pyBot(config.get('pybot','username'), config.get('pybot','password'))

Wollen nun mehrere Benutzer auf dem gleichen System den Bot benutzen, funktioniert es so nicht, da nur eine Konfigurationsdatei vorhanden ist. Jeder Benutzer sollte seine eigenen Konfigurationsdatei in seine Benutzerverzeichnis (~/.mein-pybot) besitzen.

Eine umfangreichere Version kann im Code von pySysBot gefunden werden.

Siehe auch

Diese Seite wurde zuletzt am 26. Mai 2010 um 21:41 Uhr geändert.
Diese Seite wurde bisher 1.592-mal abgerufen.

Your ip address is: 38.107.191.104


Valid XHTML 1.0 Transitional Valid XHTML 1.0 Transitional Nine Internet Solutions AG

© 2002-2009 swissjabber Marco Balmer | Co-Location by nine.ch