def __init__(self, jid, password, host, port, config): # log = logging.getLogger(__name__) print("get logger") # log.setLevel(logging.DEBUG) # print "init manager2" log.debug("in manager class2 ") log.debug("now setup the component ") logging.log(logging.DEBUG, "logging for debugging should work now.2") print(jid, password, host, port) log.debug("now setup the component ") sleekxmpp.ComponentXMPP.__init__(self, jid, password, host, port) self.config = config print("config", self.config) print("pool", self.config['pool']) print("jobs", self.config['jobs']) print("redis host", self.config['redis']['host']) print("redis port", self.config['redis']['port']) print("redis db", self.config['redis']['database']) self.redis_config = { 'host': self.config['redis']['host'], 'port': self.config['redis']['port'], 'db': self.config['redis']['database'] } self.register_plugin('xep_0030') self.register_plugin('xep_0092') self.register_plugin('xep_0004', module='kestrel.plugins.xep_0004') self.register_plugin('xep_0050', {'threaded': False}) self.register_plugin('xep_0199', {'keepalive': False}) self.register_plugin('redis_queue', self.redis_config, module='kestrel.plugins.redis_queue') self.register_plugin('redis_id', self.redis_config, module='kestrel.plugins.redis_id') self.register_plugin('redis_adhoc', self.redis_config, module='kestrel.plugins.redis_adhoc') self.register_plugin('redis_roster', self.redis_config, module='kestrel.plugins.redis_roster') self.register_plugin('kestrel_manager', { 'pool_jid': JID(self.config['pool']), 'job_jid': JID(self.config['jobs']) }, module='kestrel.plugins.kestrel_manager') self.add_event_handler("session_start", self.start) self['xep_0030'].add_identity(jid=self.boundjid.full, category='component', itype='generic', name='Kestrel', lang='en') print("init finished, now waiting ")
def __init__(self, jid, password): sleekxmpp.ClientXMPP.__init__(self, jid, password) self.logged_in = -1 self.instance_name = JID( jid).bare # para guardar el JID de este usuario self.my_contacts = {} # para guardar la información de mis contactos self.files_recv = [ ] # para guardar temporalmente un archivo que se está recibiendo (guarda data y metadata) self.add_event_handler("session_start", self.session_start, threaded=False, disposable=True) self.add_event_handler("message", self.receive_message, threaded=True, disposable=False) self.add_event_handler("failed_auth", self.on_failed_auth) self.add_event_handler("got_offline", self.contact_sign_out) self.add_event_handler("presence_unavailable", self.contact_sign_out) self.add_event_handler("got_online", self.contact_sign_in) self.add_event_handler("roster_update", self.roster_update) self.add_event_handler("changed_status", self.changed_status) self.add_event_handler("si_request", self.file_transfer_req) # self.add_event_handler("presence_subscribed", self.added_contact) # server envia mensaje de add contact success self.add_event_handler("ibb_stream_start", self.stream_opened, threaded=True) self.add_event_handler("ibb_stream_data", self.stream_data) self.add_event_handler("ibb_stream_end", self.stream_end) self.add_event_handler("groupchat_presence", self.groupchat_notif) # Registro de plugins self.register_plugin('xep_0030') # Service Discovery self.register_plugin('xep_0199') # XMPP Ping self.register_plugin('xep_0050') self.register_plugin('xep_0133') self.register_plugin('xep_0045') # MUC # file transfer self.register_plugin('xep_0047', {'auto_accept': True}) # In-band Bytestreams self.register_plugin('xep_0065') self.register_plugin('xep_0020') self.register_plugin('xep_0095') self.register_plugin('xep_0096') # SI File Transfer # If you are working with an OpenFire server, you will # need to use a different SSL version: self.ssl_version = ssl.PROTOCOL_TLS if self.connect(): print("Opened XMPP Connection") self.process(block=False) else: raise Exception("Unable to connect to server.")
def groupchat_notif(self, event): # recepción de evento en el cual un usuario ha ingresado a un chat al que ya estamos registrados. new_usr = JID(event['from']).resource status = event['status'] group = JID(event['from']).user notice = "NOTIFICACION: {} ha ingresado al chat de {}.".format( new_usr, group) notice = notice + " Mensaje de presencia: {}".format( status ) if status else notice # hay casos en los que este evento trae un mensaje de presencia custom, por lo que se muestra si es que hay alguno print(notice)
def __delitem__(self, key): """ Remove a roster item from the local storage. To remove an item from the server, use the remove() method. """ if key is None: key = JID('') if not isinstance(key, JID): key = JID(key) key = key.bare if key in self._jids: del self._jids[key]
def xmpp(request, to): if request.method == 'POST': try: s = stanza_from_string(request.body) sfrom = JID(s.get_from().full) sto = JID(s.get_to().full) except: return HttpResponse('invalid stanza\n', content_type='text/plain') if isinstance(s, Presence): stype = s._get_attr('type') if stype == 'subscribe' or stype == 'unsubscribe': out = [] # ack request resp = Presence() resp.set_from(sto) resp.set_to(sfrom) resp.set_type(stype + 'd') out.append(resp) # send presence resp = Presence() sto.resource = 'chillpad' sto.regenerate() resp.set_from(sto) resp.set_to(sfrom) if stype == 'unsubscribe': resp.set_type('unavailable') out.append(resp) return stanzas_to_response(out) elif stype == 'probe': resp = Presence() sto.resource = 'chillpad' sto.regenerate() resp.set_from(sto) resp.set_to(sfrom) return stanzas_to_response([resp]) else: # ignore return HttpResponse() elif isinstance(s, Message): is_chat = (s._get_attr('type') == 'chat') resp = Message() resp.set_from(sto) resp.set_to(sfrom) if is_chat: resp.set_type('chat') resp['body'] = 'You sent: %s' % s['body'] return stanzas_to_response([resp]) else: # be a jerk and ignore IQs return HttpResponse() else: return HttpResponseNotAllowed(['POST'])
def __getitem__(self, key): """ Return the roster item for a subscribed JID. A new item entry will be created if one does not already exist. """ if key is None: key = JID('') if not isinstance(key, JID): key = JID(key) key = key.bare if key not in self._jids: self.add(key, save=True) return self._jids[key]
def _default_get_last_activity(self, jid, node, ifrom, iq): if not isinstance(iq, Iq): reply = self.xmpp.Iq() else: iq.reply() reply = iq if jid not in self._last_activities: raise XMPPError('service-unavailable') bare = JID(jid).bare if bare != self.xmpp.boundjid.bare: if bare in self.xmpp.roster[jid]: sub = self.xmpp.roster[jid][bare]['subscription'] if sub not in ('from', 'both'): raise XMPPError('forbidden') td = datetime.now() - self._last_activities[jid]['seconds'] seconds = td.seconds + td.days * 24 * 3600 status = self._last_activities[jid]['status'] reply['last_activity']['seconds'] = seconds reply['last_activity']['status'] = status return reply
def get_last_activity(self, jid, local=False, ifrom=None, block=True, timeout=None, callback=None): if jid is not None and not isinstance(jid, JID): jid = JID(jid) if self.xmpp.is_component: if jid.domain == self.xmpp.boundjid.domain: local = True else: if str(jid) == str(self.xmpp.boundjid): local = True jid = jid.full if local or jid in (None, ''): log.debug("Looking up local last activity data for %s", jid) return self.api['get_last_activity'](jid, None, ifrom, None) iq = self.xmpp.Iq() iq['from'] = ifrom iq['to'] = jid iq['type'] = 'get' iq.enable('last_activity') return iq.send(timeout=timeout, block=block, callback=callback)
def handle_last_activity(self, iq): jid = iq['from'] if self.xmpp.is_component: # Send the uptime result = LastActivity() td = (datetime.now() - self._start_datetime) result['seconds'] = td.seconds + td.days * 24 * 3600 reply = iq.reply().setPayload(result.xml).send() else: barejid = JID(jid).bare if barejid in self.xmpp.roster and ( self.xmpp.roster[barejid]['subscription'] in ('from', 'both') or barejid == self.xmpp.boundjid.bare): # We don't know how to calculate it iq.reply().error().setPayload(iq['last_activity'].xml) iq['error']['code'] = '503' iq['error']['type'] = 'cancel' iq['error']['condition'] = 'service-unavailable' iq.send() else: iq.reply().error().setPayload(iq['last_activity'].xml) iq['error']['code'] = '403' iq['error']['type'] = 'auth' iq['error']['condition'] = 'forbidden' iq.send()
def set_items(self, values): self.del_items() for jid in values: if jid: item = ET.Element('{%s}item' % self.namespace) item.attrib['jid'] = JID(jid).full self.xml.append(item)
def test_init(self): hipchat = HipChat(nick='Sarah', jid='test@localhost', password='******', rooms=['123_homer@localhost'], plugins=(), proxy={ 'host': 'localhost', 'port': 1234, 'username': '******', 'password': '******' }) # This doesn't work with assertpy. # Does this have something to do with ABCMeta? # assert_that(hipchat).is_instance_of(HipChat) assert isinstance(hipchat, HipChat) is True assert_that(hipchat) \ .has_nick('Sarah') \ .has_rooms(['123_homer@localhost']) assert_that(hipchat.client) \ .is_instance_of(ClientXMPP) \ .has_use_proxy(True) \ .has_proxy_config({'host': 'localhost', 'port': 1234, 'username': '******', 'password': '******'}) assert_that(hipchat.client.requested_jid) \ .is_not_none() \ .is_instance_of(JID) \ .is_equal_to(JID('test@localhost', cache_lock=True))
def contact_sign_out(self, event): # recepción de notificación cuando un usuario se desconecta # se actualiza mi lista de contactos con el estado de 'offline' contact = JID(event['from']).bare if contact in self.my_contacts.keys( ): # se hace esto porque los eventos presence_unavailable también pueden venir del server self.my_contacts[contact]['state'] = "Offline" print("NOTIFICACION: {} se ha desconectado.".format(contact))
def changed_status(self, event): # recepción de evento en el que alguno de mis contactos ha actualizado su mensaje de presencia. from_usr = JID(event['from']) if event['status'] and from_usr.domain != 'conference.redes2020.xyz': # si el mensaje de presencia trae un estado, realizar el cambio y la notificacion self.my_contacts[from_usr.bare]['status_msg'] = event['status'] print( "NOTIFICACION: {} ha cambiado el mensaje de su estado a '{}'". format(from_usr.user, event['status']))
def contact_sign_in(self, event): # recepción de notificación cuando uno de mis contactos inicia sesión # se actualiza mi lista de contactos con el estado de 'online' if event['from'].domain != "conference.redes2020.xyz" and event[ 'from'] != self.instance_name: # si el presence no viene de un group chat try: self.my_contacts[JID(event['from']).bare]['state'] = "Online" self.my_contacts[JID( event['from']).bare]['fulljid'] = event["from"] self.my_contacts[JID(event['from']).bare]['status_msg'] = '' except KeyError: self.my_contacts[JID(event['from']).bare] = { 'state': 'Online', 'fulljid': event['from'], 'status_msg': '' } print("NOTIFICACION: {} se ha conectado.".format( JID(event['from']).bare))
def get_items(self): result = set() items = self.xml.findall('{%s}item' % self.namespace) if items is not None: for item in items: jid = JID(item.attrib.get('jid', '')) if jid: result.add(jid) return result
def unsubscribe(self, jid, node, subid=None, bare=True, subscribee=None, ifrom=None, block=True, callback=None, timeout=None): """ Unubscribe from updates from a pubsub node. The rules for determining the JID that is unsubscribing from the node are: 1. If subscribee is given, use that as provided. 2. If ifrom was given, use the bare or full version based on bare. 3. Otherwise, use self.xmpp.boundjid based on bare. Arguments: jid -- The pubsub service JID. node -- The node to subscribe to. subid -- The specific subscription, if multiple subscriptions exist for this JID/node combination. bare -- Indicates if the subscribee is a bare or full JID. Defaults to True for a bare JID. subscribee -- The JID that is subscribing to the node. ifrom -- Specify the sender's JID. block -- Specify if the send call will block until a response is received, or a timeout occurs. Defaults to True. timeout -- The length of time (in seconds) to wait for a response before exiting the send call if blocking is used. Defaults to sleekxmpp.xmlstream.RESPONSE_TIMEOUT callback -- Optional reference to a stream handler function. Will be executed when a reply stanza is received. """ iq = self.xmpp.Iq(sto=jid, sfrom=ifrom, stype='set') iq['pubsub']['unsubscribe']['node'] = node if subscribee is None: if ifrom: if bare: subscribee = JID(ifrom).bare else: subscribee = ifrom else: if bare: subscribee = self.xmpp.boundjid.bare else: subscribee = self.xmpp.boundjid iq['pubsub']['unsubscribe']['jid'] = subscribee iq['pubsub']['unsubscribe']['subid'] = subid return iq.send(block=block, callback=callback, timeout=timeout)
def message(self, msg): if msg['type'] in ('chat', 'normal'): print(msg) print("Body: {}".format(msg['body'])) jid = JID(msg['from']).bare nonce = msg['box'].get_nonce() box = msg['box'].get_box() print("Nonce: {}".format(nonce)) print("Box: {}".format(box)) cleartext = self.xmppSex.decryptFrom(jid, box, nonce) print("Cleartext: {}\n".format(cleartext))
def __init__(self, default_ns='jabber:client'): """ Adapt an XML stream for use with XMPP. Arguments: default_ns -- Ensure that the correct default XML namespace is used during initialization. """ XMLStream.__init__(self) # To comply with PEP8, method names now use underscores. # Deprecated method names are re-mapped for backwards compatibility. self.default_ns = default_ns self.stream_ns = 'http://etherx.jabber.org/streams' self.boundjid = JID("") self.plugin = {} self.plugin_config = {} self.plugin_whitelist = [] self.roster = {} self.is_component = False self.auto_authorize = True self.auto_subscribe = True self.sentpresence = False self.register_handler( Callback( 'IM', MatchXPath('{%s}message/{%s}body' % (self.default_ns, self.default_ns)), self._handle_message)) self.register_handler( Callback('Presence', MatchXPath("{%s}presence" % self.default_ns), self._handle_presence)) self.register_handler( Callback('Stream Error', MatchXPath("{%s}error" % self.stream_ns), self._handle_stream_error)) self.add_event_handler('presence_subscribe', self._handle_subscribe) self.add_event_handler('disconnected', self._handle_disconnected) # Set up the XML stream with XMPP's root stanzas. self.register_stanza(Message) self.register_stanza(Iq) self.register_stanza(Presence) self.register_stanza(StreamError) # Initialize a few default stanza plugins. register_stanza_plugin(Iq, Roster) register_stanza_plugin(Message, Nick) register_stanza_plugin(Message, HTMLIM)
def add(self, node): """ Add a new roster node for the given JID. Arguments: node -- The JID for the new roster node. """ if not isinstance(node, JID): node = JID(node) node = node.bare if node not in self._rosters: self._rosters[node] = RosterNode(self.xmpp, node, self.db)
def change_password(self, password, jid=None, ifrom=None, block=True, timeout=None, callback=None): iq = self.xmpp.Iq() iq['type'] = 'set' iq['to'] = jid iq['from'] = ifrom if self.xmpp.is_component: ifrom = JID(ifrom) iq['register']['username'] = ifrom.user else: iq['register']['username'] = self.xmpp.boundjid.user iq['register']['password'] = password return iq.send(block=block, timeout=timeout, callback=callback)
def add_command(self, jid=None, node=None, name='', handler=None): """ Make a new command available to external entities. Access control may be implemented in the provided handler. Command workflow is done across a sequence of command handlers. The first handler is given the initial Iq stanza of the request in order to support access control. Subsequent handlers are given only the payload items of the command. All handlers will receive the command's session data. Arguments: jid -- The JID that will expose the command. node -- The node associated with the command. name -- A human readable name for the command. handler -- A function that will generate the response to the initial command request, as well as enforcing any access control policies. """ if jid is None: jid = self.xmpp.boundjid elif not isinstance(jid, JID): jid = JID(jid) item_jid = jid.full # Client disco uses only the bare JID if self.xmpp.is_component: jid = jid.full else: jid = jid.bare self.xmpp['xep_0030'].add_identity(category='automation', itype='command-list', name='Ad-Hoc commands', node=Command.namespace, jid=jid) self.xmpp['xep_0030'].add_item(jid=item_jid, name=name, node=Command.namespace, subnode=node, ijid=jid) self.xmpp['xep_0030'].add_identity(category='automation', itype='command-node', name=name, node=node, jid=jid) self.xmpp['xep_0030'].add_feature(Command.namespace, None, jid) self.commands[(item_jid, node)] = (name, handler)
def send_presence_subscription(self, pto, pfrom=None, ptype='subscribe', pnick=None): """ Create, initialize, and send a new :class:`~sleekxmpp.stanza.presence.Presence` stanza of type ``'subscribe'``. :param pto: The recipient of a directed presence. :param pfrom: The sender of the presence. :param ptype: The type of presence, such as ``'subscribe'``. :param pnick: Optional nickname of the presence's sender. """ self.make_presence(ptype=ptype, pfrom=pfrom, pto=JID(pto).bare, pnick=pnick).send()
def roster_update(self, event): # se agrega un usuario que no estaba en mis contactos for contact in self.client_roster.keys(): contactjid = JID(contact) if (contactjid.bare not in self.my_contacts.keys()) and ( contactjid.domain != "conference.redes2020.xyz" ): # se excluye los users en el roster que sean grupos (chats) self.my_contacts[contactjid.bare] = { 'state': "Offline", 'fulljid': "", 'status_msg': '' } # se verifica si algun usuario se eliminó y se actualiza la lista de acorde deleted_clients = [] for mycontact in self.my_contacts.keys(): if mycontact not in self.client_roster.keys(): deleted_clients.append(mycontact) for delc in deleted_clients: del self.my_contacts[delc]
def patched_get_info(self, jid=None, node=None, local=None, cached=None, **kwargs): if local is None: if jid is not None and not isinstance(jid, JID): jid = JID(jid) if self.xmpp.is_component: if jid.domain == self.xmpp.boundjid.domain: local = True else: if str(jid) == str(self.xmpp.boundjid): local = True jid = jid.full elif jid in (None, ''): local = True if local: log.debug("Looking up local disco#info data " + \ "for %s, node %s.", jid, node) info = self.api['get_info'](jid, node, kwargs.get('ifrom', None), kwargs) info = self._fix_default_info(info) return self._wrap(kwargs.get('ifrom', None), jid, info) if cached: info = self.api['get_cached_info'](jid, node, kwargs.get('ifrom', None), kwargs) if info is not None: return self._wrap(kwargs.get('ifrom', None), jid, info) iq = self.xmpp.Iq() # Check dfrom parameter for backwards compatibility iq['from'] = kwargs.get('ifrom', kwargs.get('dfrom', '')) iq['from'] = self.xmpp.boundjid.bare if (not iq['from'] or iq['from'] == '') else iq['from'] iq['to'] = jid iq['type'] = 'get' iq['disco_info']['node'] = node if node else '' return iq.send(timeout=kwargs.get('timeout', None), block=kwargs.get('block', True), callback=kwargs.get('callback', None), timeout_callback=kwargs.get('timeout_callback', None))
def __getitem__(self, key): """ Return the roster node for a JID. A new roster node will be created if one does not already exist. Arguments: key -- Return the roster for this JID. """ if key is None: key = self.xmpp.boundjid if not isinstance(key, JID): key = JID(key) key = key.bare if key not in self._rosters: self.add(key) self._rosters[key].auto_authorize = self.auto_authorize self._rosters[key].auto_subscribe = self.auto_subscribe return self._rosters[key]
def _unserialize_session(self, session): """ Modify a session dictionary to undo the modifications made in order to pickle the session. Note: Modifies the session in place. """ if '__JID__' in session: for key in session['__JID__']: session[key] = JID(session['__JID__'][key]) del session['__JID__'] if '__XML__' in session: for key in session['__XML__']: stanza_class, xml = session['__XML__'][key] xml = ET.fromstring(xml) session[key] = stanza_class(xml=xml) del session['__XML__'] if '__FUNC__' in session: for key in session['__FUNC__']: func_hash = session['__FUNC__'][key] session[key] = self.funcs[func_hash] del session['__FUNC__']
def session_start(self, event): try: self.send_presence() # se envía presence inicial al server self.get_roster(block=True, timeout=5) # parse del roster para obtener estado de los contactos # print("contacts in client roster", self.client_roster) for contact in self.client_roster.keys(): self.my_contacts[JID(contact).bare] = { 'state': "Offline", 'fulljid': "", 'status_msg': '' } # print("Joined rooms:", ", ".join(list(self.plugin['xep_0045'].getJoinedRooms()))) self.logged_in = 0 # una vez esté loggeado correctamente, se hace saber al main.py que ya puede imprimir el menú siguiente except IqError as err: logging.error('There was an error getting the roster') logging.error(err.iq['error']['condition']) self.disconnect() except IqTimeout: logging.error('Server is taking too long to respond') self.disconnect()
# Using Facebook or MSN's custom authentication requires # a browser, but the process is the same once a token # has been retrieved. # Request an access token from Google: try: conn = HTTPSConnection('www.google.com') except: print('Could not connect to Google') sys.exit() params = urlencode({ 'accountType': 'GOOGLE', 'service': 'mail', 'Email': JID(opts.jid).bare, 'Passwd': opts.password }) headers = {'Content-Type': 'application/x-www-form-urlencoded'} try: conn.request('POST', '/accounts/ClientLogin', params, headers) resp = conn.getresponse().read() data = {} for line in resp.split(): k, v = line.split(b'=', 1) data[k] = v except Exception as e: print('Could not retrieve login data') sys.exit() if b'SID' not in data:
def getJid(self): item = self.getXMLItem() return JID(item.get('jid', ''))
def get_info(self, jid=None, node=None, local=False, cached=None, **kwargs): """ Retrieve the disco#info results from a given JID/node combination. Info may be retrieved from both local resources and remote agents; the local parameter indicates if the information should be gathered by executing the local node handlers, or if a disco#info stanza must be generated and sent. If requesting items from a local JID/node, then only a DiscoInfo stanza will be returned. Otherwise, an Iq stanza will be returned. Arguments: jid -- Request info from this JID. node -- The particular node to query. local -- If true, then the query is for a JID/node combination handled by this Sleek instance and no stanzas need to be sent. Otherwise, a disco stanza must be sent to the remove JID to retrieve the info. cached -- If true, then look for the disco info data from the local cache system. If no results are found, send the query as usual. The self.use_cache setting must be set to true for this option to be useful. If set to false, then the cache will be skipped, even if a result has already been cached. Defaults to false. ifrom -- Specifiy the sender's JID. block -- If true, block and wait for the stanzas' reply. timeout -- The time in seconds to block while waiting for a reply. If None, then wait indefinitely. The timeout value is only used when block=True. callback -- Optional callback to execute when a reply is received instead of blocking and waiting for the reply. """ if jid is not None and not isinstance(jid, JID): jid = JID(jid) if self.xmpp.is_component: if jid.domain == self.xmpp.boundjid.domain: local = True else: if str(jid) == str(self.xmpp.boundjid): local = True jid = jid.full elif jid in (None, ''): local = True if local: log.debug("Looking up local disco#info data " + \ "for %s, node %s.", jid, node) info = self.api['get_info'](jid, node, kwargs.get('ifrom', None), kwargs) info = self._fix_default_info(info) return self._wrap(kwargs.get('ifrom', None), jid, info) if cached: log.debug("Looking up cached disco#info data " + \ "for %s, node %s.", jid, node) info = self.api['get_cached_info'](jid, node, kwargs.get('ifrom', None), kwargs) if info is not None: return self._wrap(kwargs.get('ifrom', None), jid, info) iq = self.xmpp.Iq() # Check dfrom parameter for backwards compatibility iq['from'] = kwargs.get('ifrom', kwargs.get('dfrom', '')) iq['to'] = jid iq['type'] = 'get' iq['disco_info']['node'] = node if node else '' return iq.send(timeout=kwargs.get('timeout', None), block=kwargs.get('block', True), callback=kwargs.get('callback', None))