async def _handle_disco_items(self, iq: Iq): """ Process an incoming disco#items stanza. If it is a get request, find and return the appropriate items. If it is an items result, fire the disco_items event. :param iq: The incoming disco#items stanza. """ if iq['type'] == 'get': log.debug("Received disco items query from " "<%s> to <%s>.", iq['from'], iq['to']) items = await self.api['get_items'](iq['to'], iq['disco_items']['node'], iq['from'], iq) if isinstance(items, Iq): items.send() else: iq = iq.reply() if items: iq.set_payload(items.xml) iq.send() elif iq['type'] == 'result': log.debug("Received disco items result from " "%s to %s.", iq['from'], iq['to']) self.xmpp.event('disco_items', iq)
async def _handle_get_vcard(self, iq: Iq): if iq['type'] == 'result': await self.api['set_vcard'](jid=iq['from'], args=iq['vcard_temp']) return elif iq['type'] == 'get' and self.xmpp.is_component: vcard = await self.api['get_vcard'](iq['to'].bare, ifrom=iq['from']) if isinstance(vcard, Iq): vcard.send() else: iq = iq.reply() iq.append(vcard) iq.send() elif iq['type'] == 'set': raise XMPPError('service-unavailable')
async def _handle_registration(self, iq: Iq): if iq["type"] == "get": await self._send_form(iq) elif iq["type"] == "set": if iq["register"]["remove"]: try: await self.api["user_remove"](None, None, iq["from"], iq) except KeyError: _send_error( iq, "404", "cancel", "item-not-found", "User not found", ) else: reply = iq.reply() reply.send() self.xmpp.event("user_unregister", iq) return for field in self.form_fields: if not iq["register"][field]: # Incomplete Registration _send_error( iq, "406", "modify", "not-acceptable", "Please fill in all fields.", ) return try: await self.api["user_validate"](None, None, iq["from"], iq["register"]) except ValueError as e: _send_error( iq, "406", "modify", "not-acceptable", e.args, ) else: reply = iq.reply() reply.send() self.xmpp.event("user_register", iq)
def _handle_version(self, iq: Iq): """ Respond to a software version query. :param iq: The Iq stanza containing the software version query. """ iq = iq.reply() if self.software_name: iq['software_version']['name'] = self.software_name iq['software_version']['version'] = self.version iq['software_version']['os'] = self.os else: iq.error() iq['error']['type'] = 'cancel' iq['error']['condition'] = 'service-unavailable' iq.send()
def _default_get_last_activity(self, jid: JID, node: str, ifrom: JID, iq: Iq) -> Iq: if not isinstance(iq, Iq): reply = self.xmpp.Iq() else: reply = iq.reply() 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 Iq(self, *args, **kwargs): """ Create an Iq stanza. Uses same arguments as StanzaBase.__init__ Arguments: xml -- An XML object to use for the Iq's values. """ return Iq(self.xmpp, *args, **kwargs)
async def send_push(self, user, jid, values, checked=True): # called when a subscription is being changed iq = Iq(self.stream) iq['type'] = 'set' iq['roster'].set_items({jid.bare: values}) if checked: type = 'roster.push' else: type = 'roster.push_unchecked' await self.stream.ipc_send(type, user, iq.xml)
async def _handle_bob_iq(self, iq: Iq): cid = iq['bob']['cid'] if iq['type'] == 'result': await self.api['set_bob'](iq['from'], None, iq['to'], args=iq['bob']) self.xmpp.event('bob', iq) elif iq['type'] == 'get': data = await self.api['get_bob'](iq['to'], None, iq['from'], args=cid) if isinstance(data, Iq): data['id'] = iq['id'] data.send() return iq = iq.reply() iq.append(data) iq.send()
async def _handle_disco_info(self, iq: Iq): """ Process an incoming disco#info stanza. If it is a get request, find and return the appropriate identities and features. If it is an info result, fire the disco_info event. :param iq: The incoming disco#items stanza. """ if iq['type'] == 'get': log.debug("Received disco info query from " "<%s> to <%s>.", iq['from'], iq['to']) info = await self.api['get_info'](iq['to'], iq['disco_info']['node'], iq['from'], iq) if isinstance(info, Iq): info['id'] = iq['id'] info.send() else: node = iq['disco_info']['node'] iq = iq.reply() if info: info = self._fix_default_info(info) info['node'] = node iq.set_payload(info.xml) iq.send() elif iq['type'] == 'result': log.debug("Received disco info result from " "<%s> to <%s>.", iq['from'], iq['to']) if self.use_cache: log.debug("Caching disco info result from " "<%s> to <%s>.", iq['from'], iq['to']) if self.xmpp.is_component: ito = iq['to'].full else: ito = None await self.api['cache_info'](iq['from'], iq['disco_info']['node'], ito, iq) self.xmpp.event('disco_info', iq)
async def _handle_open_request(self, iq: Iq): sid = iq['ibb_open']['sid'] size = iq['ibb_open']['block_size'] or self.block_size log.debug('Received IBB stream request from %s', iq['from']) if not sid: raise XMPPError(etype='modify', condition='bad-request') if not await self._accept_stream(iq): raise XMPPError(etype='cancel', condition='not-acceptable') if size > self.max_block_size: raise XMPPError('resource-constraint') stream = IBBytestream(self.xmpp, sid, size, iq['to'], iq['from']) stream.stream_started = True await self.api['set_stream'](stream.self_jid, stream.sid, stream.peer_jid, stream) iq.reply().send() self.xmpp.event('ibb_stream_start', stream) self.xmpp.event('stream:%s:%s' % (sid, stream.peer_jid), stream)
async def _relay_push(self, xml, checked): if checked: # Though the IPC push messages do give us notification that # the database has changed, messages are not guaranteed to # arrive in the same order that the database was updated. # So just in case, we should get up-to-date information from # the database before relaying any pushes to the user. iq = Iq(self.stream, xml) contacts = iq['roster'].get_items() for jid, values in contacts.items(): values = await self.stream.roster_hook.get_contact( self.stream.boundjid, jid) if values is None: values = {'subscription': 'remove'} contacts[jid] = values iq['roster'].set_items(contacts) xml = iq.xml self.stream.send_element(xml)
async def _make_registration_form(self, jid, node, ifrom, iq: Iq): reg = iq["register"] user = await self.api["user_get"](None, None, iq['from'], iq) if user is None: user = {} else: reg["registered"] = True reg["instructions"] = self.form_instructions for field in self.form_fields: data = user.get(field, "") if data: reg[field] = data else: # Add a blank field reg.add_field(field) reply = iq.reply() reply.set_payload(reg.xml) return reply
def Iq(self, *args, **kwargs): """Create an Iq stanza associated with this stream.""" return Iq(self, *args, **kwargs)