Jabber/XMPP conference bot & framework
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
brathuhn/brathuhn.py

235 lines
7.3 KiB

import xmpp, os, sys, time
from config import *
VERSION = "0.2"
commands = dict()
commands_private = dict()
group_listeners = []
private_listeners = []
status_listeners = []
users = dict()
STATUS_JOIN, STATUS_ONLINE, STATUS_OFFLINE, STATUS_RENAME, STATUS_XAWAY, STATUS_AWAY, STATUS_UNKNOWN = range(7)
def getUsers():
"""Return a dictionary of every user in the group, the values are status codes."""
return users
def addCommand(name,help,func):
"""Add a groupchat command.
@param name -- The name of the command, if the command keyword
"!name" is used at the start of a message the given
handler will be called
@param help -- Help string displayed on with the !help command
@param func -- Handler of the form func(msg,args) where msg is the
xmpppy representation of the message sent and args is
a list of arguments"""
commands[name]=(help,func)
def addPrivateCommand(name,help,func):
"""Add a private chat command.
@param name -- The name of the command, if the command keyword
"!name" is used at the start of a message the given
handler will be called
@param help -- Help string displayed on with the !help command
@param func -- Handler of the form func(msg,args) where msg is the
xmpppy representation of the message sent and args is
a list of arguments"""
commands_private[name]=(help,func)
def addGroupListener(func):
"""Add a groupchat listener.
@param func -- Handler of the form func(from,msg) where both arguments
are unicode strings"""
group_listeners.append(func)
def addPrivateListener(func):
"""Adds a private chat listener.
@param func -- Handler of the form func(from,msg) where both arguments
are unicode strings"""
private_listeners.append(func)
def addStatusListener(func):
"""Adds a user status listener.
@param func -- Handler of the form func(from,msg,status) where first two
arguments are unicode strings and status is one of STATUS_*
constants"""
status_listeners.append(func)
def sendMsg(to,body,mtype=None):
"""Send a message to the server.
@param to -- Recipient of the message
@param body -- Message body
@param mtype -- Type of the message, (e.g. "groupchat" for group
messages)"""
mymsg = xmpp.protocol.Message(body=body)
mymsg.setTo(to)
if mtype!=None:
mymsg.setType(mtype)
cl.send(mymsg)
def sendStyledMsg(to,body,mtype=None,style=""):
"""Send a CSS-styled message to the server.
@param to -- Recipient of the message
@param body -- Message body
@param mtype -- Type of the message, (e.g. "groupchat" for group
messages)
@param style -- Inline CSS used to format the message"""
mymsg = xmpp.protocol.Message(body=body)
mymsg.setTo(to)
if mtype!=None:
mymsg.setType(mtype)
c=mymsg.addChild('html', namespace='http://jabber.org/protocol/xhtml-im')
c=c.addChild('body',namespace='http://www.w3.org/1999/xhtml')
c=c.addChild('span',payload=body,attrs={'style':style})
cl.send(mymsg)
def sendMonoMsg(to,body,mtype=None):
"""Send a mono-spaced styled message to the server (e.g. ASCII art).
@param to -- Recipient of the message
@param body -- Message body
@param mtype -- Type of the message, (e.g. "groupchat" for group
messages)"""
mymsg = xmpp.protocol.Message(body=body)
mymsg.setTo(to)
mymsg.setType(mtype)
c=mymsg.addChild('html', namespace='http://jabber.org/protocol/xhtml-im')
c=c.addChild('body',namespace='http://www.w3.org/1999/xhtml')
c=c.addChild('span', attrs={'style':'font-family: Courier New, monospace;'})
c=c.addChild('pre',payload=body,attrs={'style':'background-color: #ffffff;'})
cl.send(mymsg)
def __help(msg,args):
sendMsg(ROOM,"Available commands:",'groupchat')
for cmd in commands:
sendMsg(ROOM," !"+cmd+" - "+commands[cmd][0],'groupchat')
sendMsg(ROOM,"Available private chat commands:",'groupchat')
for cmd in commands_private:
sendMsg(ROOM," !"+cmd+" - "+commands_private[cmd][0],'groupchat')
def __messageCB(conn,msg):
if msg.getType() == "groupchat":
#print unicode(msg.getFrom()) +": "+ unicode(msg.getBody()) +" " +unicode(msg.getChildren())
body = unicode(msg.getBody())
mfrom = unicode(msg.getFrom())
if NAME in body and not room_nick in mfrom:
sendMsg(ROOM,NAME+" --(brathuhn bot framework (v"+VERSION+"), type !help)",'groupchat')
for cmd in commands:
if body.startswith("!"+cmd) and not room_nick in mfrom:
args = body.split()
commands[cmd][1](msg,args)
for listener in group_listeners:
listener( unicode(msg.getFrom()), unicode(msg.getBody()))
if msg.getType() == "chat":
if msg.getBody() != None:
body = unicode(msg.getBody())
mfrom = unicode(msg.getFrom())
for cmd in commands_private:
if body.startswith("!"+cmd) and not room_nick in mfrom:
args = body.split()
commands_private[cmd][1](msg,args)
for listener in private_listeners:
listener( mfrom, body)
raise xmpp.NodeProcessed
def __presenceCB(conn,msg):
#print "Status",msg.getFrom(), msg.getStatus(), msg.getStatusCode(), msg.getType()
if msg.getType()=='unavailable':
nick=msg.getNick()
if nick==None:
del users[msg.getFrom()]
#Disconnect
if not msg.getFrom() in users:
for listener in status_listeners:
listener(msg.getFrom(),msg,STATUS_OFFLINE)
else:
del users[msg.getFrom()]
#Rename
if not msg.getFrom() in users:
for listener in status_listeners:
listener(msg.getFrom(),msg,STATUS_RENAME)
else:
show = msg.getShow()
if show==None:
if not msg.getFrom() in users:
for listener in status_listeners:
listener(msg.getFrom(),msg,STATUS_JOIN)
users[msg.getFrom()] = STATUS_ONLINE
#Online
else:
print msg.getFrom(),"is now",show
if not msg.getFrom() in users:
for listener in status_listeners:
listener(msg.getFrom(),msg,STATUS_JOIN)
if show=="away":
users[msg.getFrom()] = STATUS_AWAY
elif show=="xa":
users[msg.getFrom()] = STATUS_XAWAY
else:
users[msg.getFrom()] = STATUS_UNKNOWN
# status change
status = STATUS_OFFLINE
if msg.getFrom() in users:
status = users[msg.getFrom()]
for listener in status_listeners:
listener(msg.getFrom(),msg.getStatus(),status)
jid=xmpp.protocol.JID(node=NAME,domain=SRV,resource='bot')
cl=xmpp.Client(jid.getDomain(),debug=[])
def connect_and_join():
"""Connect to the server and join the group chat room from the config."""
global room_nick
global room_to
#connect to server
con=cl.connect()
if not con:
print 'could not connect!'
sys.exit()
print 'connected'
cl.RegisterHandler('message',__messageCB)
cl.RegisterHandler('presence',__presenceCB)
#authenticate
auth=cl.auth(NAME,PWD,resource=jid.getResource())
if not auth:
print 'could not authenticate!'
sys.exit()
print 'auth'
room_to = "%s/%s" % (ROOM, NAME)
room_nick = ROOM+"/"+NAME
msg = xmpp.Presence(to=room_to)
if PWD_ROOM != "":
msg.addChild('x', namespace='http://jabber.org/protocol/muc').addChild('password',payload=PWD_ROOM)
#add the help command
addCommand("help","Prints this help message",__help)
#join the room
cl.send(msg)
#set status
cl.send(xmpp.Presence(to=room_to,status=NAME+" --(brathuhn bot framework (v"+VERSION+"), type !help)"))
def loop():
"""Loop forever and handle the event-queue."""
while True:
cl.Process(1)