# core/bots/xmpp.py
#
#
""" basic package for the program. """
__copyright__ = "Copyright 2015, B.H.J Thate"
## IMPORTS
from core.kernel import kernel, fleet, cfg
from core.cfg import cfg_xmpp
from core.bots import Bot
from core.thing import Thing
import threading
import logging
import getpass
import queue
## XMPP
[docs]class XMPP(Bot):
""" XMPP Bot. """
cc = "none"
default = ""
def __init__(zelf, *args, **kwargs):
import sleekxmpp
from sleekxmpp import clientxmpp
Bot.__init__(zelf, *args, **kwargs)
if "port" not in zelf: zelf.port = cfg_xmpp.port
zelf._queue = queue.Queue()
zelf.client = clientxmpp.ClientXMPP(zelf.user, getpass.getpass())
zelf.client.add_event_handler("session_start", zelf.session_start)
zelf.client.add_event_handler("message", zelf.messaged)
zelf.client.add_event_handler('disconnected', zelf.disconnected)
zelf.client.add_event_handler('connected', zelf.connected)
zelf.client.add_event_handler('presence_available', zelf.presenced)
zelf.client.add_event_handler('presence_dnd', zelf.presenced)
zelf.client.add_event_handler('presence_xa', zelf.presenced)
zelf.client.add_event_handler('presence_chat', zelf.presenced)
zelf.client.add_event_handler('presence_away', zelf.presenced)
zelf.client.add_event_handler('presence_unavailable', zelf.presenced)
zelf.client.add_event_handler('presence_subscribe', zelf.presenced)
zelf.client.add_event_handler('presence_subscribed', zelf.presenced)
zelf.client.add_event_handler('presence_unsubscribe', zelf.presenced)
zelf.client.add_event_handler('presence_unsubscribed', zelf.presenced)
zelf.client.add_event_handler('groupchat_message', zelf.messaged)
zelf.client.add_event_handler('groupchat_presence', zelf.presenced)
zelf.client.add_event_handler('groupchat_subject', zelf.presenced)
zelf.client.add_event_handler('failed_auth', zelf.failedauth)
zelf.client.exception = zelf.exception
zelf.client.use_signals()
zelf._connected = threading.Event()
zelf.channels = []
[docs] def raw(zelf, *args, **kwargs):
logging.debug("> %s/write %s" % (zelf.type, args[0]))
zelf.client.send_raw(args[0])
[docs] def start(zelf, *args, **kwargs):
zelf.connect()
Bot.start(zelf, *args, **kwargs)
[docs] def connect(zelf):
logging.warn("# %s/connect %s" % (zelf.type, zelf.user))
if cfg.openfire:
logging.warn("# %s/openfire" % zelf.type)
import ssl
zelf.client.ssl_version = ssl.PROTOCOL_SSLv3
zelf.client.connect((zelf.server, zelf.port), use_ssl=True)
else: zelf.client.connect((zelf.server, zelf.port))
[docs] def session_start(zelf, event):
zelf.client.send_presence()
zelf.ready()
logging.warn("# %s/session %s" % (zelf.type, zelf.user))
[docs] def exception(zelf, ex):
zelf._status = ex
logging.error("^ %s/error %s"% (zelf.type, str(ex)))
[docs] def announce(zelf, *args, **kwargs):
for channel in zelf.channels: zelf.say(channel, args[0])
[docs] def failedauth(zelf, error, *args, **kwargs): zelf._error = error ; logging.error("^ %s/auth %s" % (zelf.type, str(error)))
[docs] def failure(zelf, error, *args, **kwargs): zelf._error = error ; logging.error("^ %s/error %s" % (zelf.type, str(error)))
[docs] def disconnected(zelf, *args, **kwargs):
zelf._connected.clear()
zelf._status = "disconnect"
logging.warn("^ %s/disconnect %s" % (zelf.type, zelf.user))
[docs] def connected(zelf, *args, **kwargs):
zelf._status = "connected"
zelf._connected.set()
logging.warn("# %s/connected %s" % (zelf.type, zelf.user))
[docs] def loop(zelf, *args, **kwargs): zelf.client.process()
[docs] def say(zelf, *args, **kwargs):
to = args[0]
txt = args[1]
zelf.client.send_message(to, txt)
logging.info("> %s/say %s" % (zelf.type, to))
[docs] def event(zelf, *args, **kwargs): return zelf._queue.get()
[docs] def messaged(zelf, data, *args, **kwargs):
logging.debug("< %s/read %s" % (zelf.type, str(data["data"])))
m = Thing(**data)
if m.type == "error": logging.error("^ %s" % m.error) ; return
m.cc = zelf.cc
m["from"] = str(m["from"])
if zelf.user in m["from"]: logging.warn("%s/%s %s" % (zelf.type, m.type, m["from"])) ; return
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("# %s/ignore %s %s" % (zelf.type, m.type, m.origin))
return
logging.warn("< %s/%s %s" % (zelf.type, m.type, m.origin))
zelf._queue.put_nowait(m)
[docs] def presenced(zelf, data, *args, **kwargs):
logging.info("< %s/%s %s" % (zelf.type, "presence", data["data"]))
o = Thing(data)
o["from"] = str(o["from"])
o.origin = o["from"]
if "txt" not in o: o.txt = ""
o.element = "presence"
if o.type == 'subscribe':
pres = Thing({'to': o["from"], 'type': 'subscribed'})
zelf.client.send_presence(pres)
pres = Thing({'to': o["from"], 'type': 'subscribe'})
zelf.client.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("< %s/%s %s" % (zelf.type, o.type, o.origin))
zelf._queue.put_nowait(o)
[docs] def exit(zelf, *args, **kwargs):
zelf.client.disconnect()
Bot.exit(zelf)
zelf._queue.put(None)
[docs]def init(*args, **kwargs):
cfg = Thing().last("cfg", "xmpp")
if not cfg: cfg = cfg_xmpp ; cfg.save()
xmpp = XMPP(**cfg)
fleet.append(xmpp)
kernel.put(xmpp.loop)
kernel.put(xmpp.start)