class FoosBot(object): def __init__(self, jid, password): # we set this as an attribute instead of sublcassing because many # of ClientXMPP's attributes are named something we might accidentally # overrite (breaking ClientXMPP). it's happened to me quite a bit self.xmpp = ClientXMPP(jid, password) self.xmpp.add_event_handler("session_start", self._session_start_handler) self.xmpp.add_event_handler("message", self._message_handler) self.xmpp.register_plugin('xep_0030') # Service Discovery self.xmpp.register_plugin('xep_0199') # XMPP Ping self.match_requested = False self.active_players = {} self.match_players = [] self.state_machines = {} def start(self): self.xmpp.connect(('talk.google.com', 5222)) self.xmpp.process(block=True) def _session_start_handler(self, event): self.xmpp.send_presence() # Most get_*/set_* methods from plugins use Iq stanzas, which # can generate IqError and IqTimeout exceptions try: self.xmpp.get_roster() except IqError as err: logging.error('There was an error getting the roster') logging.error(err.iq['error']['condition']) self.xmpp.disconnect() except IqTimeout: logging.error('Server is taking too long to respond') self.xmpp.disconnect() def _message_handler(self, msg): if msg['type'] not in ('chat', 'normal'): # TODO Add logging return sender = str(msg["from"]).split("/")[0] body = str(msg["body"]).strip().lower() game_creator = self.state_machines.get(sender) if not game_creator: self.state_machines[sender] = GameCreator(sender) game_creator = self.state_machines.get(sender) reply = game_creator.handle_message(sender, body) if reply: self.send(sender, reply) def send(self, to, message): if not isinstance(to, (tuple, list)): to = [to] message = str(message) # evaluates Template, if it exists for player in to: self.xmpp.send_message(player, message)
class XMPPNotifier(BaseNotifier): regex = re.compile('^xmpp:([^:@\s]+@[^:@\s]+)$') def __init__(self, config): self.config = config self.started = False self.xmpp = ClientXMPP( self.config['username'], self.config['password'] ) self.xmpp.add_event_handler('session_start', self.start) self.xmpp.connect(address=self.config['server'], use_tls=True) self.xmpp.process() def start(self, event): self.xmpp.send_presence() self.xmpp.get_roster() self.started = True def notify(self, contact, node): msg = node.format_infotext(self.config['text']) receipient = self.regex.match(contact).group(1) self.xmpp.send_message(mto=receipient, mbody=msg, mtype='chat') return True def quit(self): while not self.started: sleep(0.5) self.xmpp.disconnect(wait=True)
class XMPPConnection(Connection): def __init__(self, jid, password): self.connected = False self.client = ClientXMPP(jid, password, plugin_config={'feature_mechanisms': XMPP_FEATURE_MECHANISMS}) 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.add_event_handler("session_start", self.session_start) def send_message(self, mess): self.client.send_message(mto=mess.getTo(), mbody=mess.getBody(), mtype=mess.getType(), mhtml=mess.getHTML()) def session_start(self, event): self.client.send_presence() self.client.get_roster() def connect(self): if not self.connected: 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(block=True) def add_event_handler(self, name, cb): self.client.add_event_handler(name, cb) def join_room(self, room, username, password): muc = self.client.plugin['xep_0045'] muc.joinMUC(room, username, password=password, wait=True) form = muc.getRoomForm(room) if form: muc.configureRoom(room, form) else: logging.error("Error configuring the MUC Room %s" % room)
class XMPPConnection(Connection): def __init__(self, jid, password): self.connected = False self.client = ClientXMPP( jid, password, plugin_config={'feature_mechanisms': XMPP_FEATURE_MECHANISMS}) self.client.register_plugin('xep_0030') # Service Discovery self.client.register_plugin('xep_0045') # Multi-User Chat self.client.register_plugin( 'xep_0004' ) # Multi-User Chat backward compability (necessary for join room) 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 XMPP_KEEPALIVE_INTERVAL is not None: self.client.whitespace_keepalive = True # Just in case SleekXMPP's default changes to False in the future self.client.whitespace_keepalive_interval = XMPP_KEEPALIVE_INTERVAL self.client.ca_certs = XMPP_CA_CERT_FILE # Used for TLS certificate validation self.client.add_event_handler("session_start", self.session_start) self.client.add_event_handler("ssl_invalid_cert", self.ssl_invalid_cert) def send_message(self, mess): self.client.send_message(mto=mess.getTo(), mbody=mess.getBody(), mtype=mess.getType(), mhtml=mess.getHTML()) def session_start(self, _): self.client.send_presence() self.client.get_roster() def ssl_invalid_cert(self, _): # Special quirk for google domains verify_gtalk_cert(self.client) def connect(self): if not self.connected: 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(block=True) 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) def join_room(self, room, username, password): """Attempt to join the given MUC""" muc = self.client.plugin['xep_0045'] muc.joinMUC(room, username, password=password, wait=True) # Room configuration can only be done once a MUC presence stanza # has been received from the server. This HAS to take place in a # separate thread because of how SleekXMPP processes these stanzas. t = Thread(target=self.configure_room, args=[room]) t.setDaemon(True) t.start() def configure_room(self, room): """ Configure the given MUC Currently this simply sets the default room configuration as received by the server. May be extended in the future to set a custom room configuration instead. """ muc = self.client.plugin['xep_0045'] affiliation = None while affiliation is None: sleep(0.5) affiliation = muc.getJidProperty(room=room, nick=muc.ourNicks[room], jidProperty='affiliation') if affiliation == "owner": logging.debug( "Configuring room {} because we have owner affiliation".format( room)) form = muc.getRoomConfig(room) muc.configureRoom(room, form) else: logging.debug( "Not configuring room {} because we don't have owner affiliation (affiliation={})" .format(room, affiliation)) def invite_in_room(self, room, jids_to_invite): muc = self.client.plugin['xep_0045'] for jid in jids_to_invite: logging.debug("Inviting %s to %s..." % (jid, room)) muc.invite(room, jid)
class XMPPConnection(Connection): def __init__(self, jid, password): self.connected = False self.client = ClientXMPP( jid, password, plugin_config={'feature_mechanisms': XMPP_FEATURE_MECHANISMS}) self.client.register_plugin('xep_0030') # Service Discovery self.client.register_plugin('xep_0045') # Multi-User Chat self.client.register_plugin( 'old_0004' ) # Multi-User Chat backward compability (necessary for join room) 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 XMPP_KEEPALIVE_INTERVAL is not None: self.client.whitespace_keepalive = True # Just in case SleekXMPP's default changes to False in the future self.client.whitespace_keepalive_interval = XMPP_KEEPALIVE_INTERVAL self.client.add_event_handler("session_start", self.session_start) self.client.add_event_handler("ssl_invalid_cert", self.ssl_invalid_cert) def send_message(self, mess): self.client.send_message(mto=mess.getTo(), mbody=mess.getBody(), mtype=mess.getType(), mhtml=mess.getHTML()) def session_start(self, _): self.client.send_presence() self.client.get_roster() def ssl_invalid_cert(self, _): # Special quirk for google domains verify_gtalk_cert(self.client) def connect(self): if not self.connected: 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(block=True) def add_event_handler(self, name, cb): self.client.add_event_handler(name, cb) def join_room(self, room, username, password): muc = self.client.plugin['xep_0045'] muc.joinMUC(room, username, password=password, wait=True) form = muc.getRoomForm(room) if form: muc.configureRoom(room, form) else: logging.error("Error configuring the MUC Room %s" % room) def invite_in_room(self, room, jids_to_invite): muc = self.client.plugin['xep_0045'] for jid in jids_to_invite: logging.debug("Inviting %s to %s..." % (jid, room)) muc.invite(room, jid)
class FoosBot(object): def __init__(self, jid, password): # we set this as an attribute instead of sublcassing because many # of ClientXMPP's attributes are named something we might accidentally # overrite (breaking ClientXMPP). it's happened to me quite a bit self.xmpp = ClientXMPP(jid, password) self.xmpp.add_event_handler("session_start", self._session_start_handler) self.xmpp.add_event_handler("message", self._message_handler) self.xmpp.register_plugin("xep_0030") # Service Discovery self.xmpp.register_plugin("xep_0199") # XMPP Ping self.match_requested = False self.active_players = {} self.match_players = [] self.state_machines = {} def start(self): self.xmpp.connect(("talk.google.com", 5222)) self.xmpp.process(block=True) def _session_start_handler(self, event): self.xmpp.send_presence() # Most get_*/set_* methods from plugins use Iq stanzas, which # can generate IqError and IqTimeout exceptions try: self.xmpp.get_roster() except IqError as err: logging.error("There was an error getting the roster") logging.error(err.iq["error"]["condition"]) self.xmpp.disconnect() except IqTimeout: logging.error("Server is taking too long to respond") self.xmpp.disconnect() def _message_handler(self, msg): if msg["type"] not in ("chat", "normal"): # TODO Add logging return sender = str(msg["from"]).split("/")[0] body = str(msg["body"]).strip().lower() game_creator = self.state_machines.get(sender) if not game_creator: self.state_machines[sender] = GameCreator(sender) game_creator = self.state_machines.get(sender) reply = game_creator.handle_message(sender, body) if reply: self.send(sender, reply) def send(self, to, message): if not isinstance(to, (tuple, list)): to = [to] message = str(message) # evaluates Template, if it exists for player in to: self.xmpp.send_message(player, message)
Created on Mon Dec 9 22:50:45 2019 @author: tema """ import urllib.request import time from sleekxmpp import ClientXMPP username = '******' passwd = '0q1u0a1n2t0u0m' to = '*****@*****.**' client = ClientXMPP(username, passwd) client.connect() client.process() while True: req = urllib.request.Request('http://weather.nsu.ru/weather.xml') response = urllib.request.urlopen(req) page = response.read() str_page = str(page) index1 = str_page.find('current') index2 = str_page.find('/current') data = str_page[index1 + 8:index2 - 1] client.send_message(to, 'Current temperature: ' + data + '°C') time.sleep(1) client.disconnect()
class XMPPConnection(Connection): def __init__(self, jid, password): self.connected = False self.client = ClientXMPP(jid, password, plugin_config={'feature_mechanisms': XMPP_FEATURE_MECHANISMS}) self.client.register_plugin('xep_0030') # Service Discovery self.client.register_plugin('xep_0045') # Multi-User Chat self.client.register_plugin('old_0004') # Multi-User Chat backward compability (necessary for join room) 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 XMPP_KEEPALIVE_INTERVAL is not None: self.client.whitespace_keepalive = True # Just in case SleekXMPP's default changes to False in the future self.client.whitespace_keepalive_interval = XMPP_KEEPALIVE_INTERVAL self.client.ca_certs = XMPP_CA_CERT_FILE # Used for TLS certificate validation self.client.add_event_handler("session_start", self.session_start) self.client.add_event_handler("ssl_invalid_cert", self.ssl_invalid_cert) def send_message(self, mess): self.client.send_message(mto=mess.getTo(), mbody=mess.getBody(), mtype=mess.getType(), mhtml=mess.getHTML()) def session_start(self, _): self.client.send_presence() self.client.get_roster() def ssl_invalid_cert(self, _): # Special quirk for google domains verify_gtalk_cert(self.client) def connect(self): if not self.connected: 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(block=True) def add_event_handler(self, name, cb): self.client.add_event_handler(name, cb) def join_room(self, room, username, password): muc = self.client.plugin['xep_0045'] muc.joinMUC(room, username, password=password, wait=True) form = muc.getRoomForm(room) if form: muc.configureRoom(room, form) else: logging.error("Error configuring the MUC Room %s" % room) def invite_in_room(self, room, jids_to_invite): muc = self.client.plugin['xep_0045'] for jid in jids_to_invite: logging.debug("Inviting %s to %s..." % (jid, room)) muc.invite(room, jid)
class XmppBot: """ Interfaces with Jabber and identifies bosses by JID and resource. """ def __init__(self, connect_cfg): "Initialize XMPP bot" # (Sender JID, [local resource]) -> callback self.dispatch_map = {} self.jid = connect_cfg.jid self.connect(connect_cfg) def connect(self, config): "Connect to XMPP server" socks_cfg = config.get('socks_proxy', required=False) self.client = ClientXMPP(self.jid, config.password) proxy_cfg = config.get('http_proxy', required=False) if proxy_cfg is not None: self.client.use_proxy = True self.client.proxy_config = { 'host': proxy_cfg.host, 'port': proxy_cfg.get('port', assert_type=int), 'username': proxy_cfg.get('username', required=False), 'password': proxy_cfg.get('password', required=False), } print("Configured proxy", self.client.proxy_config) use_tls = config.get('tls', default=True) # Events self.client.add_event_handler("session_start", self._session_start) self.client.add_event_handler("message", self.message_dispatch) log.info("Initializing connection to XMPP") ip = config.get('ip', required=False) if ip is not None: print("port", config.port) port = config.get('port', default=5222, assert_type=int) self.client.connect((ip, port), use_tls=use_tls) else: self.client.connect(use_tls=use_tls) def _session_start(self, event): log.info('Starting XMPP session') self.client.send_presence() def add_dispatch(self, sender_jid, resource, callback): """ Register callback to handle incoming messages from sender_jid directed to a given resource (can be None to mean "any"). """ key = (sender_jid, resource) if key in self.dispatch_map: raise Exception("Sender JID duplicated: %s" % sender_jid) self.dispatch_map[key] = callback def message_dispatch(self, msg): "Dispatch incoming message depending on the sender" if msg['type'] not in ('chat', 'normal'): log.warning('Unknown message type: %r %r', msg, msg['type']) return to_jid = msg.get_to() from_jid = msg.get_from() resource = to_jid.resource def respond(response): "Closure to simplify responding" self.send_message(from_jid, response) log.debug("Got message:") log.debug("From: %s, to: %s", from_jid, to_jid) log.debug("Body: %r", msg) # Dispatch direct (to resource) or generic (to JID) callback = self.dispatch_map.get((from_jid.bare, resource), None) if callback is None: callback = self.dispatch_map.get((from_jid.bare, None), None) # If unknown - ignore if callback is None: respond(language.get('DONT_KNOW')) return # Construct a Message using bot-generic API message = Message(msg['body'], from_jid.full, respond) callback(message) message.finish() def send_message(self, jid, message): "Send a message" self.client.send_message(jid, message) def close(self): "Disconnect / close threads" self.client.abort()
class XMPPConnection(Connection): def __init__(self, jid, password): self.connected = False self.client = ClientXMPP(jid, password, plugin_config={'feature_mechanisms': XMPP_FEATURE_MECHANISMS}) self.client.register_plugin('xep_0030') # Service Discovery self.client.register_plugin('xep_0045') # Multi-User Chat self.client.register_plugin('xep_0004') # Multi-User Chat backward compability (necessary for join room) 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 XMPP_KEEPALIVE_INTERVAL is not None: self.client.whitespace_keepalive = True # Just in case SleekXMPP's default changes to False in the future self.client.whitespace_keepalive_interval = XMPP_KEEPALIVE_INTERVAL self.client.ca_certs = XMPP_CA_CERT_FILE # Used for TLS certificate validation self.client.add_event_handler("session_start", self.session_start) self.client.add_event_handler("ssl_invalid_cert", self.ssl_invalid_cert) def send_message(self, mess): self.client.send_message(mto=mess.getTo(), mbody=mess.getBody(), mtype=mess.getType(), mhtml=mess.getHTML()) def session_start(self, _): self.client.send_presence() self.client.get_roster() def ssl_invalid_cert(self, _): # Special quirk for google domains verify_gtalk_cert(self.client) def connect(self): if not self.connected: 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(block=True) 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) def join_room(self, room, username, password): """Attempt to join the given MUC""" muc = self.client.plugin['xep_0045'] muc.joinMUC(room, username, password=password, wait=True) # Room configuration can only be done once a MUC presence stanza # has been received from the server. This HAS to take place in a # separate thread because of how SleekXMPP processes these stanzas. t = Thread(target=self.configure_room, args=[room]) t.setDaemon(True) t.start() def configure_room(self, room): """ Configure the given MUC Currently this simply sets the default room configuration as received by the server. May be extended in the future to set a custom room configuration instead. """ muc = self.client.plugin['xep_0045'] affiliation = None while affiliation is None: sleep(0.5) affiliation = muc.getJidProperty( room=room, nick=muc.ourNicks[room], jidProperty='affiliation' ) if affiliation == "owner": logging.debug("Configuring room {} because we have owner affiliation".format(room)) form = muc.getRoomConfig(room) muc.configureRoom(room, form) else: logging.debug("Not configuring room {} because we don't have owner affiliation (affiliation={})" .format(room, affiliation)) def invite_in_room(self, room, jids_to_invite): muc = self.client.plugin['xep_0045'] for jid in jids_to_invite: logging.debug("Inviting %s to %s..." % (jid, room)) muc.invite(room, jid)
def send_chatroom_message(self, context, message): # Get context session = self.__get_session(context) res_id = context.reservation.reservation_id current_user = context.reservation.running_user admin_user, admin_password, api_server, api_port = self.__get_openfire_server_details( context, session) # Chatroom name is current sandbox name chatroom_name = session.GetReservationDetails( reservationId=res_id).ReservationDescription.Name # Chatroom ID is reservation id chatroom_id = res_id # Get XMPP domain value xmpp_domain = self.__get_xmpp_domain(server=api_server, port=api_port, user=admin_user, password=admin_password) # Construct full Jabber user id JID = "%s@%s" % (admin_user, xmpp_domain) session.WriteMessageToReservationOutput( context.reservation.reservation_id, "\nSending message to chat room \"%s\" as %s" % (chatroom_name, current_user)) xmpp = ClientXMPP(jid=JID, password=admin_password) xmpp.register_plugin('xep_0045') conn = xmpp.connect(use_ssl=False, use_tls=False, address=(api_server, '5222')) room = '%s@conference.%s' % (chatroom_id, xmpp_domain) # need to join chat room before sending message session.WriteMessageToReservationOutput( context.reservation.reservation_id, " Joining room") xmpp.plugin['xep_0045'].joinMUC( room, current_user, wait=True, ) # Send message to room xmpp.send_message(mtype='groupchat', mbody=message, mto=room, mnick=current_user) # Run commands above session.WriteMessageToReservationOutput( context.reservation.reservation_id, " Sending message \"%s\"" % message) session.WriteMessageToReservationOutput( context.reservation.reservation_id, "Completed") xmpp.process(block=False) # Ensure we have enough time to send the message before disconnecting time.sleep(5) xmpp.disconnect() pass
from sleekxmpp import ClientXMPP from lxml import etree DELAY = 5 username = '******' passwd = 'enterjb2' to = ['*****@*****.**', '*****@*****.**'] client = ClientXMPP(username, passwd) client.connect() client.process() xml = etree.parse('http://weather.nsu.ru/weather.xml') temp = xml.xpath('/weather/current/text()')[0] message = 'Current temperature: ' + temp + '°C' for t in to: client.send_message(t, message) print('Sent: \'' + message + '\'') while True: xml = etree.parse('http://weather.nsu.ru/weather.xml') new_temp = xml.xpath('/weather/current/text()')[0] if new_temp != temp: temp = new_temp message = 'Current temperature: ' + temp + '°C' for t in to: client.send_message(t, message) print('Sent: \'' + message + '\'') client.disconnect()
class XMPPCommunicator(Communicator): def __del__(self): self.disconnect() def __init__(self, jid, passwd, contacts, accept_from=None, greeting="XMPP communication established", verbosity = 2, answer=None): # also initialize ClientXMPP self.xmpp = ClientXMPP(jid, passwd) self.jid = jid self.passwd = passwd self.contacts = contacts self.greeting = greeting self.accept_from = accept_from self.verbosity = verbosity self.messages = [] self.xmpp.add_event_handler("session_start", self._start_xmpp) self.xmpp.add_event_handler("message", self._buffer_message) self.xmpp.register_plugin('xep_0030') # Service Discovery self.xmpp.register_plugin('xep_0199') # XMPP Ping if answer == None: self.answer = lambda daemon, comm, msg: None else: self.answer = answer def prepare(self, daemon): self.connect() self.process() def _start_xmpp(self, event): self.xmpp.send_presence() self.xmpp.get_roster() print "[jodaepy] " + self.greeting self.send_message(self.greeting) def _buffer_message(self, msg): if msg['type'] in ['normal', 'chat']: if self.accept_from == None or msg['from'] in self.accept_from: self.messages.append(msg['body']) def connect(self): return self.xmpp.connect() def disconnect(self): return self.xmpp.disconnect() def process(self): return self.xmpp.process(block=False) def send_message(self, mbody, contacts = None): contacts = self.contacts if not contacts else contacts for contact in contacts: self.xmpp.send_message( mto=contact, mbody=mbody, mtype='chat' ) def registration_failed(self, daemon, error): if self.verbosity > 1: self.send_message("Registration Failed: " + str(error) + "\n") def finalization_failed(self, daemon, job, error): if self.verbosity > 1: self.send_message("Finalization Failed (job %d): " % job.id + str(error) + "\n") def starting_failed(self, daemon, job, error): if self.verbosity > 1: self.send_message("Could not start job (job %d): " % job.id + str(error) + "\n") def postprocessing_failed(self, daemon, error): if self.verbosity > 1: self.send_message("Postprocessing failed: " + str(error) + "\n") def workspace_updated(self, deamon, files): if self.verbosity > 1: if files: self.send_message("Found files " + " ".join(files) + "\n") def scripts_updated(self, deamon, scripts): if self.verbosity > 1: if scripts: self.send_message("Found scripts " + " ".join(scripts) + "\n") def jobs_registered(self, daemon, jobs): if self.verbosity > 1: if jobs: msg = [] msg.append("Found jobs\n") for job in jobs: msg.append(" %5d '%s'\n" % (job.id, job.title) ) self.send_message(''.join(msg)) def jobs_started(self, daemon, jobs): if self.verbosity > 1: if jobs: msg = [] msg.append("Started jobs\n") for job in jobs: msg.append(" %5d, on '%s'\n" % (job.id, job.running_host) ) self.send_message(''.join(msg)) def jobs_returned(self, daemon, jobs): pass def jobs_finalized(self, daemon, jobs): if self.verbosity > 1: if jobs: msg = [] msg.append("Finalized jobs\n") for job in jobs: msg.append(" %5d (%s), %s -- %s\n" % \ (job.id, "fail" if job.failed() else "sucess", job.stime, job.ftime) ) self.send_message(''.join(msg)) def postprocessing_done(self, daemon, pp): if self.verbosity > 1: if pp: self.send_message("Postprocessing done\n") def host_unavailable(self, daemon, job): if self.verbosity > 1: self.send_message("Expected hosts %s for job %d are unavailable. Dropped this job\n" % (str(job.hosts), job.id) ) def job_updated(self, daemon, job, dpercs, doutfiles): perc_old, perc = dpercs outfiles_old, outfiles= doutfiles if self.verbosity < 3: return if self.verbosity == 3: if perc_old < 25 and perc > 25 or \ perc_old < 50 and perc > 50 or \ perc_old < 75 and perc > 75: self.send_message("Job %d: %d%% completed\n" % (job.id, perc) ) def communicate(self, daemon): for message in self.messages: self.answer(daemon, self, message) self.messages = [] def close(): self.disconnect()
class XMPPService(ServiceHandler): """ Service handler for XMPP. Configuration options: type = XMPP jid = [email protected] password = the password ; Relay messages from these rooms. (Optional) receiver_rooms = [email protected] ; Broadcast messages to these rooms. (Optional) broadcaster_rooms = [email protected] ; Relay direct messages from these users or ALL. (Optional) receiver_jids = ALL ; Broadcast messages to these users. (Optional) broadcaster_jids = [email protected] """ def __init__(self, config): super().__init__(config) self.client = ClientXMPP(config["jid"], config["password"]) self.client.add_event_handler("session_start", self._xmpp_connected_event) self.client.add_event_handler("message", self._xmpp_msg_received_event) self.client.add_event_handler("groupchat_message", self._xmpp_muc_msg_received_event) self.client.register_plugin("xep_0045") # Multi-User Chat async def _on_stop(self): self.client.disconnect() async def _on_start(self): # This automatically runs in a seperate thread # TODO: Is this needed when we are asynchronous anyways? self.client.connect() self.client.process() async def _on_send_message(self, msg): for room in self.config.get("broadcaster_rooms", []): self.client.send_message(mto=room, mbody=msg, mtype="groupchat") for jid in self.config.get("broadcaster_jids", []): self.client.send_message(mto=jid, mbody=msg, mtype="chat") def _xmpp_msg_received_event(self, msg): # Ignore our own messages at all costs if msg["from"].bare == self.config["jid"] \ or msg.get("mucnick", "") == self.client.boundjid.username: return if msg["type"] == "chat": # If we do not receive from ALL and the JID is not in the list, ignore. if not ("ALL" in self.config.get("receiver_jids", []) or msg["from"].bare in self.config.get("receiver_jids", [])): return channel = "PM" author = msg["from"].bare elif msg["type"] == "groupchat": if msg["mucroom"] not in self.config.get("receiver_rooms", []): return channel = msg["mucroom"] author = msg["mucnick"] else: print("Received unknown XMPP message: %s" % msg) return future = super()._on_receive_message(msg=msg["body"], source_channel=channel, source_nick=author) asyncio.run_coroutine_threadsafe(future, self.loop) def _xmpp_muc_msg_received_event(self, msg): # Group messages also trigger the message event, so this might not be needed. pass def _xmpp_connected_event(self, event): self.client.send_presence() # self.client.get_roster() if self.is_receiver(): for room in self.config.get("receiver_rooms", []): print("Joining %s" % room) self.client.plugin["xep_0045"].joinMUC( room, self.client.boundjid.username, wait=True) if self.is_broadcaster(): for room in self.config.get("broadcaster_rooms", []): # Skip already joined rooms if room in self.client.plugin["xep_0045"].getJoinedRooms(): continue print("Joining %s" % room) self.client.plugin["xep_0045"].joinMUC( room, self.client.boundjid.username, wait=True) asyncio.run_coroutine_threadsafe(super()._on_started(), self.loop) @staticmethod def requested_config_values(): return { "jid": ConfigType(Subtype.LOGIN_INFO, required=True), "password": ConfigType(Subtype.LOGIN_INFO, required=True), "broadcaster_rooms": ConfigType(Subtype.BROADCAST_FILTER, multi_value=True), "receiver_rooms": ConfigType(Subtype.RECEIVE_FILTER, multi_value=True), "broadcaster_jids": ConfigType(Subtype.BROADCAST_FILTER, multi_value=True), "receiver_jids": ConfigType(Subtype.RECEIVE_FILTER, multi_value=True) }