Jak na bota v pythonu

Obrázek uživatele kamahl@jabbim.cz
Vložil kamahl@jabbim.cz, Út, 2007-06-12 11:47 :: | | |

Napsat bota pro mě vždycky bylo vždy lákavé už za dob ICQ, ale tam jsem se o to ani nepokoušel, byla by to spousta námahy pro nic. Nedávno se mi podařilo napsat bota pro xmpp v pythonu s použitím modulu, kupodivu xmpp, a nebylo to vůbec těžké, přestože tutoriálů a dokumentace je opravdu nedostatek. S vámi, kdo byste si ho také rádi vyrobili a nevíte jak na to, jsem právě takový tutoriál připravil.

Předpokládám, že máte alespoň základní znalosti o pythonu. K práci budeme samozřejmě potřebovat onen modul, v Debianu to byl balík python-xmpp. Jdem na to!

#!/usr/bin/python
#-*-coding:UTF-8-*-
import sys, xmpp
if len(sys.argv) < 3:
print "Použití: %s JID heslo" % sys.argv[0]
sys.exit()

Tohle je vám jasné teď se připojíme k serveru. Program budeme spouštět takto: ./bot.py JID heslo

jid = xmpp.JID(sys.argv[1]) # Vytvoří objekt jid, pro získávání dalších informací
server = jid.getDomain() # Npříklad takových, proměnnou nahazuji jen pro přehlednost
spojeni = xmpp.Client(server) # Vytvoří objekt spojení, to nejdůležitější na celém programu
# Můžete nastavit ještě port (defaultně 5222) a debug ([] pro vypnutí)
spojeni_res = spojeni.connect() # Naváže spojení a vrátí řetězec resource (Ne ta část JID za lomítkem, je to např. "tsl"!)
# Dají se nastavit ještě parametry server a proxy
if not spojeni_res:
print "Nepodařilo se navázat spojení se serverem %s" % server
sys.exit(1)
# Tento oddíl by snad měl být jasný, nyní provedeme něco podobného s autentizací
zdroj = "Bot" # Pokud nezadáme, vygeneruje se náhodné ošklivé číslo
auth_res = spojeni.auth(jid.getNode(), sys.argv[2], zdroj) # Tady vrací nepř. "sasl"
# jid.getNode() je ta část před @, sys.argv[2] je heslo, to jen pro osvěžení paměti
if not auth_res:
print "Autentizace se nazdařila! Zkontrolujte JID a heslo"
sys.exit(2)

Hurá, nejtěžší část máme za sebou. Nyní budeme muset vytvořit a připojit nějaké handlery ve formě funkcí. To bude veškeré umění vašeho bota a tady už záleží na tom jak jste dobří pythonýři. Vysvětlím to hned následovně tak se nelekejte parametrů. Třeba takhle:

def odpoved(spojeni, zprava):
body = zprava.getBody() # Zpráva je objekt, který se funkci předá, getBody() vrátí její obsah
jid = zprava.getFrom() # Opět je to jen objekt jid!
spojeni.send(xmpp.Message(jid, body.upper(), typ="chat"))
# Odešle zprávu zpět, akorát velkým písmem. Opravdu tam je "typ" a né "type"
# Nebo můžete zkusit oblíbený opouštěč icq
#if jid.getDomain() == "icq.netlab.cz": # Nebo váš server s transportem
#spojeni.send(xmpp.Message(jid, "ICQ kurva nevedu!", typ="chat"))

Teď už je potřeba jen připojit handler k události. Je to úplně snadné.

spojeni.RegisterHandler("message", odpoved)

Místo "message" může být samozřejmě třeba "iq", druhý parametr je funkce, které předá parametry spojeni a obsah přijatých dat, který si zpracuje sama. To všechno krásně vidíme na její definici. Teď řekneme světu ahoj:

spojeni.sendInitPresence()

Ale protože nechceme aby bot hned zase skončil, musíme vyrobit hlavní cyklus, ale to už je zívačka.

def krok(spojeni):
try: spojeni.Process(1)
except KeyboardInterrupt: return 0
return 1
while krok(spojeni): pass

A jsme hotovi! Že to nebolelo?
Jestli najdete nějakou syntaktickou chybu nebo bug, tak mi prosím napište.
Odkazy:
Jabber - komunikačný protokol Popis jabber protokolu a programování v Javě.
Generovaná API dokumentace modulu xmpp.