# zot/bots/xmpp.py
#
#
""" basic package for the program. """
__copyright__ = "Copyright 2015, B.H.J Thate"
## IMPORTS
from zot.defines import BLA, GREEN, ENDC, pfc
from zot.runtime import kernel, fleet, cfg
from zot.object import Object
from zot.defaults import cfg_xmpp
from zot.utils import stripped
from zot.bot import BOT
import threading
import logging
import getpass
import queue
import time
import html
## XMPP
[docs]class XMPP(BOT):
""" XMPP bot. """
cc = ""
def __init__(zelf, *args, **kwargs):
import sleekxmpp
from sleekxmpp import clientxmpp
BOT.__init__(zelf, *args, **kwargs)
if "port" not in zelf: zelf.port = 5222
zelf._queue = queue.Queue()
zelf.xmpp = clientxmpp.ClientXMPP(zelf.user, getpass.getpass())
zelf.xmpp.add_event_handler("session_start", zelf.session_start)
zelf.xmpp.add_event_handler("message", zelf.handle_message)
zelf.xmpp.add_event_handler('disconnected', zelf.handle_disconnected)
zelf.xmpp.add_event_handler('connected', zelf.handle_connected)
zelf.xmpp.add_event_handler('presence_available', zelf.handle_presence)
zelf.xmpp.add_event_handler('presence_dnd', zelf.handle_presence)
zelf.xmpp.add_event_handler('presence_xa', zelf.handle_presence)
zelf.xmpp.add_event_handler('presence_chat', zelf.handle_presence)
zelf.xmpp.add_event_handler('presence_away', zelf.handle_presence)
zelf.xmpp.add_event_handler('presence_unavailable', zelf.handle_presence)
zelf.xmpp.add_event_handler('presence_subscribe', zelf.handle_presence)
zelf.xmpp.add_event_handler('presence_subscribed', zelf.handle_presence)
zelf.xmpp.add_event_handler('presence_unsubscribe', zelf.handle_presence)
zelf.xmpp.add_event_handler('presence_unsubscribed', zelf.handle_presence)
zelf.xmpp.add_event_handler('groupchat_message', zelf.handle_message)
zelf.xmpp.add_event_handler('groupchat_presence', zelf.handle_presence)
zelf.xmpp.add_event_handler('groupchat_subject', zelf.handle_presence)
zelf.xmpp.add_event_handler('failed_auth', zelf.handle_failedauth)
zelf.xmpp.exception = zelf.exception
zelf.xmpp.use_signals()
zelf.openfire = cfg.openfire
if zelf.openfire:
logging.warn("! XMPP/enable openfire")
import ssl
zelf.xmpp.ssl_version = ssl.PROTOCOL_SSLv3
zelf._connected = threading.Event()
zelf.channels = []
def _raw(zelf, *args, **kwargs):
logging.debug("> XMPP/raw %s" % args[0])
zelf.xmpp.send_raw(args[0])
[docs] def start(zelf, *args, **kwargs):
zelf.connect()
BOT.start(zelf, *args, **kwargs)
[docs] def connect(zelf):
logging.error("! XMPP/connecting %s" % zelf.server)
try: zelf.xmpp.connect((zelf.server, zelf.port), use_ssl=zelf.openfire)
except: zelf.xmpp.connect((zelf.server, zelf.port))
[docs] def session_start(zelf, event):
zelf.xmpp.send_presence()
zelf.ready()
logging.error("! XMPP/session established %s" % zelf.user)
[docs] def exception(zelf, ex):
zelf._status = ex
logging.error("! XMPP/error %s"% str(ex))
[docs] def announce(zelf, *args, **kwargs):
zelf.wait()
for channel in zelf.channels: zelf.say(channel, args[0])
[docs] def handle_failedauth(zelf, error, *args, **kwargs): zelf._error = error ; logging.error("! XMPP/auth %s" % str(error))
[docs] def handle_failure(zelf, error, *args, **kwargs): zelf._error = error ; logging.error("! XMPP/failure %s" % str(error))
[docs] def handle_disconnected(zelf, *args, **kwargs):
zelf._connected.clear()
zelf._status = "disconnected"
logging.error("! XMPP/disconnected %s" % zelf.user)
[docs] def handle_connected(zelf, *args, **kwargs):
zelf._status = "running"
zelf._connected.set()
logging.error("! XMPP/connected %s" % zelf.user)
[docs] def loop(zelf, *args, **kwargs): zelf.xmpp.process(block=True)
[docs] def say(zelf, *args, **kwargs):
to = args[0]
txt = args[1]
zelf.xmpp.send_message(to, txt)
logging.info("> XMPP/message %s" % to)
[docs] def event(zelf, *args, **kwargs):
event = zelf._queue.get()
event.cc = zelf.cc
return event
[docs] def handle_message(zelf, data, *args, **kwargs):
logging.debug("< XMPP/raw %s" % data)
m = Object(**data)
if m.type == "error": logging.error(m.error) ; return
m["from"] = str(m["from"])
m.origin = m["from"]
m.channel = m.origin
m.to = m.origin
m.element = "message"
m.txt = m["body"]
m._target = zelf
if '<delay xmlns="urn:xmpp:delay"' in str(data):
logging.warn("! XMPP/ignore %s %s" % (m.type, m.origin))
return
logging.warn("! XMPP/%s %s" % (m.type, m.origin))
zelf._queue.put(m)
[docs] def handle_presence(zelf, data, *args, **kwargs):
logging.debug("< XMPP/raw %s" % data)
o = Object(data)
o["from"] = str(o["from"])
o.origin = o["from"]
o.element = "presence"
if o.type == 'subscribe':
pres = Object({'to': o["from"], 'type': 'subscribed'})
o.xmpp.send_presence(pres)
pres = Object({'to': o["from"], 'type': 'subscribe'})
o.xmpp.send_presence(pres)
elif o.type == "unavailable":
if o.origin in zelf.channels: zelf.channels.remove(o.origin)
else:
if o.origin != zelf.user and o.origin not in zelf.channels: zelf.channels.append(o.origin)
o.no_dispatch = True
o._target = zelf
logging.warn("! XMPP/%s %s" % (o.type, o.origin))
zelf._queue.put(o)
[docs] def exit(zelf, *args, **kwargs):
zelf.xmpp.disconnect()
Bot.exit(zelf)
zelf._queue.put(None)
[docs]def init(*args, **kwargs):
cfg = Object().last("cfg", "xmpp")
if not cfg: cfg = cfg_xmpp ; cfg.save()
bot = XMPP(**cfg)
fleet.append(bot)
kernel.put(bot.loop)
kernel.put(bot.start)