class XMPPConnection(object): def __init__(self, jid, password, feature=None, keepalive=None, ca_cert=None, server=None, use_ipv6=None, bot=None, ssl_version=None): if feature is None: feature = {} self._bot = bot self.connected = False self.server = server self.client = ClientXMPP(jid, password, plugin_config={'feature_mechanisms': feature}) self.client.register_plugin('xep_0030') # Service Discovery self.client.register_plugin('xep_0045') # Multi-User Chat self.client.register_plugin('xep_0199') # XMPP Ping self.client.register_plugin('xep_0203') # XMPP Delayed messages self.client.register_plugin('xep_0249') # XMPP direct MUC invites if keepalive is not None: self.client.whitespace_keepalive = True # Just in case Slixmpp's default changes to False in the future self.client.whitespace_keepalive_interval = keepalive if use_ipv6 is not None: self.client.use_ipv6 = use_ipv6 if ssl_version: self.client.ssl_version = ssl_version self.client.ca_certs = ca_cert # Used for TLS certificate validation self.client.add_event_handler("session_start", self.session_start) def session_start(self, _): self.client.send_presence() self.client.get_roster() def connect(self): if not self.connected: if self.server is not None: self.client.connect(self.server) else: self.client.connect() self.connected = True return self def disconnect(self): self.client.disconnect(wait=True) self.connected = False def serve_forever(self): self.client.process() def add_event_handler(self, name, cb): self.client.add_event_handler(name, cb) def del_event_handler(self, name, cb): self.client.del_event_handler(name, cb)
class HipchatClient(object): def __init__(self, broadcast_msg): self.broadcast_msg = broadcast_msg self.conn_lock = asyncio.Lock() # force locking now # it seems that the xmpp server really doesn't like it when you send messages # before the setup is complete, so lock everything until we've authed and joined all the rooms. [_ for _ in self.conn_lock.acquire()] self.c = ClientXMPP(self.jabber_id, self.password) self.c.register_plugin('xep_0030') # Service Discovery self.c.register_plugin('xep_0045') # Multi-User Chat self.c.register_plugin('xep_0199') # XMPP Ping self.c.register_plugin('xep_0203') # XMPP Delayed messages self.c.register_plugin('xep_0249') # XMPP direct MUC invites self.c.auto_authorize = True self.c.auto_subscribe = True self.c.whitespace_keepalive = True self.c.whitespace_keepalive_interval = 60 self.c.add_event_handler('session_bind', self.session_start) self.c.add_event_handler('session_bind', self.c._start_keepalive) for room, _ in self.rooms: self.c.add_event_handler('muc::{}::message'.format(room), self.muc_message) self.c.add_event_handler('muc::{}::got_offline'.format(room), functools.partial(self.send_presence, 'parted')) self.c.add_event_handler('muc::{}::got_online'.format(room), functools.partial(self.send_presence, 'joined')) self.c.connect() def session_start(self, event): self.c.send_presence() self.c.get_roster() for room, password in self.rooms: self.c.plugin['xep_0045'].joinMUC(room, self.nickname, password=password, wait=True) self.conn_lock.release() def muc_message(self, msg): # yes, this is how you check to see if 'delay' is set on a message. # this API is dumb if isinstance(msg['delay']['stamp'], datetime.datetime): return if msg['from'].resource == self.nickname: return self.broadcast_msg(self.format_msg(msg)) def format_msg(self, msg): return '({0}) {1}'.format(msg['from'].resource, msg['body']) def format_presence(self, user, status): return '*** {0} has {1}'.format(user, status) def send_presence(self, status, msg): self.broadcast_msg(self.format_presence(msg['from'].resource, status)) @asyncio.coroutine def send_msg(self, msg): with (yield from self.conn_lock): for room, _ in self.rooms: self.c.send_message(mto=room, mbody=msg, mtype='groupchat')