def set_value(self, value): del self['value'] valXMLName = '{%s}value' % self.namespace if self._type == 'boolean': if value in self.true_values: valXML = ET.Element(valXMLName) valXML.text = '1' self.xml.append(valXML) else: valXML = ET.Element(valXMLName) valXML.text = '0' self.xml.append(valXML) elif self._type in self.multi_value_types or self._type in ('', None): if isinstance(value, bool): value = [value] if not isinstance(value, list): value = value.replace('\r', '') value = value.split('\n') for val in value: if self._type in ('', None) and val in self.true_values: val = '1' valXML = ET.Element(valXMLName) valXML.text = val self.xml.append(valXML) else: if isinstance(value, list): raise ValueError("Cannot add multiple values " + \ "to a %s field." % self._type) valXML = ET.Element(valXMLName) valXML.text = value self.xml.append(valXML)
def setAffiliation(self, room, jid=None, nick=None, affiliation='member', ifrom=None): """ Change room affiliation.""" if affiliation not in ('outcast', 'member', 'admin', 'owner', 'none'): raise TypeError query = ET.Element('{http://jabber.org/protocol/muc#admin}query') if nick is not None: item = ET.Element('{http://jabber.org/protocol/muc#admin}item', { 'affiliation': affiliation, 'nick': nick }) else: item = ET.Element('{http://jabber.org/protocol/muc#admin}item', { 'affiliation': affiliation, 'jid': jid }) query.append(item) iq = self.xmpp.make_iq_set(query) iq['to'] = room iq['from'] = ifrom # For now, swallow errors to preserve existing API try: result = iq.send() except IqError: return False except IqTimeout: return False return True
def join_muc(self, room, nick, maxhistory="0", password='', wait=False, pstatus=None, pshow=None, pfrom=None): """ Join the specified room, requesting 'maxhistory' lines of history. """ stanza = self.xmpp.make_presence(pto="%s/%s" % (room, nick), pstatus=pstatus, pshow=pshow, pfrom=pfrom) x = ET.Element('{http://jabber.org/protocol/muc}x') if password: passelement = ET.Element('{http://jabber.org/protocol/muc}password') passelement.text = password x.append(passelement) if maxhistory: history = ET.Element('{http://jabber.org/protocol/muc}history') if maxhistory == "0": history.attrib['maxchars'] = maxhistory else: history.attrib['maxstanzas'] = maxhistory x.append(history) stanza.append(x) if not wait: self.xmpp.send(stanza) else: #wait for our own room presence back expect = ET.Element("{%s}presence" % self.xmpp.default_ns, {'from':"%s/%s" % (room, nick)}) self.xmpp.send(stanza, expect) self.rooms[room] = {} self.our_nicks[room] = nick
def py2xml(*args): params = ET.Element("{%s}params" % _namespace) for x in args: param = ET.Element("{%s}param" % _namespace) param.append(_py2xml(x)) params.append(param) #<params><param>... return params
def cancelConfig(self, room, ifrom=None): query = ET.Element('{http://jabber.org/protocol/muc#owner}query') x = ET.Element('{jabber:x:data}x', type='cancel') query.append(x) iq = self.xmpp.make_iq_set(query) iq['to'] = room iq['from'] = ifrom iq.send()
def set_users(self, values): users = self.xml.find('{%s}users' % self.namespace) if users is None: users = ET.Element('{%s}users' % self.namespace) self.xml.append(users) for resource in values: res = ET.Element('{%s}resource' % self.namespace) res.text = resource users.append(res)
def set_types(self, value): del self['types'] for type_ in value: if type_ == 'emphasis': self.xml.append(ET.Element('{urn:xmpp:markup:0}emphasis')) elif type_ == 'code': self.xml.append(ET.Element('{urn:xmpp:markup:0}code')) elif type_ == 'deleted': self.xml.append(ET.Element('{urn:xmpp:markup:0}deleted'))
def get_users_by_affiliation(cls, room, affiliation='member', ifrom=None): if affiliation not in ('outcast', 'member', 'admin', 'owner', 'none'): raise TypeError query = ET.Element('{http://jabber.org/protocol/muc#admin}query') item = ET.Element('{http://jabber.org/protocol/muc#admin}item', {'affiliation': affiliation}) query.append(item) iq = cls.xmpp.Iq(sto=room, sfrom=ifrom, stype='get') iq.append(query) return iq.send()
def invite(self, room, jid, reason='', mfrom=''): """ Invite a jid to a room.""" msg = self.xmpp.make_message(room) msg['from'] = mfrom x = ET.Element('{http://jabber.org/protocol/muc#user}x') invite = ET.Element('{http://jabber.org/protocol/muc#user}invite', {'to': jid}) if reason: rxml = ET.Element('{http://jabber.org/protocol/muc#user}reason') rxml.text = reason invite.append(rxml) x.append(invite) msg.append(x) self.xmpp.send(msg)
def set_item_attr(self, attr, value: str): item = self.xml.find(f'{{{NS_USER}}}item') if item is None: item = ET.Element(f'{{{NS_USER}}}item') self.xml.append(item) item.attrib[attr] = value return item
async def get_token(self): """Called when the XMPP session has been initialized.""" iq_cmd = self.Iq() iq_cmd['type'] = 'get' action_cmd = ET.Element('oa') action_cmd.attrib['xmlns'] = 'connect.logitech.com' action_cmd.attrib['mime'] = 'vnd.logitech.connect/vnd.logitech.pair' action_cmd.text = 'method=pair:name={0}'.format('pyharmony#iOS10.1#iPhone') iq_cmd.set_payload(action_cmd) result = await iq_cmd.send() payload = result.get_payload() if len(payload) != 1: raise HarmonyException('Bad payload from hub') response = payload[0] result_code = response.attrib['errorcode'] if result_code != '200': raise HarmonyException( 'Bad response code from hub: {0}'.format(result_code) ) match = re.search(r'identity=(?P<uuid>[\w-]+):status', response.text) if not match: raise HarmonyException( 'Token not found in response' ) return match.group('uuid')
def add_identity(self, category, itype, name=None, lang=None): """ Add a new identity element. Each identity must be unique in terms of all four identity components. Multiple, identical category/type pairs are allowed only if the xml:lang values are different. Likewise, multiple category/type/xml:lang pairs are allowed so long as the names are different. In any case, a category and type are required. Arguments: category -- The general category to which the agent belongs. itype -- A more specific designation with the category. name -- Optional human readable name for this identity. lang -- Optional standard xml:lang value. """ identity = (category, itype, lang) if identity not in self._identities: self._identities.add(identity) id_xml = ET.Element('{%s}identity' % self.namespace) id_xml.attrib['category'] = category id_xml.attrib['type'] = itype if lang: id_xml.attrib['{%s}lang' % self.xml_ns] = lang if name: id_xml.attrib['name'] = name self.xml.insert(0, id_xml) return True return False
def del_chat_state(self): parent = self.parent() for state in self.states: state_xml = parent.find('{%s}%s' % (self.namespace, state)) if state_xml is not None: self.xml = ET.Element('') parent.xml.remove(state_xml)
async def send_request(self, mime, command=None, block=True): iq_cmd = self.Iq() iq_cmd['type'] = 'get' action_cmd = ET.Element('oa') action_cmd.attrib['xmlns'] = XMLNS action_cmd.attrib['mime'] = mime if command is not None: action_cmd.text = command iq_cmd.set_payload(action_cmd) try: if block: result = await iq_cmd.send() else: iq_cmd.send() except (IqError, IqTimeout): raise HarmonyException('Error sending command to hub') if block: payload = result.get_payload() if len(payload) != 1: raise HarmonyException('Bad payload from hub') response = payload[0] result_code = response.attrib['errorcode'] if result_code != '200': raise HarmonyException( 'Bad response code from hub: {0}'.format(result_code) ) return response.text
def fault2xml(code: int, message: str) -> ET.Element: value: Dict[str, Any] = dict() value["faultCode"] = code value["faultString"] = message fault = ET.Element("fault", {"xmlns": _namespace}) fault.append(_py2xml((value, ))) return fault
def add_reported(self, var, ftype=None, label='', desc='', **kwargs): kwtype = kwargs.get('type', None) if kwtype is None: kwtype = ftype reported = self.xml.find('{%s}reported' % self.namespace) if reported is None: reported = ET.Element('{%s}reported' % self.namespace) self.xml.append(reported) fieldXML = ET.Element('{%s}field' % FormField.namespace) reported.append(fieldXML) field = FormField(xml=fieldXML) field['var'] = var field['type'] = kwtype field['label'] = label field['desc'] = desc return field
def set_binval(self, value): self.del_binval() parent = self.parent() if value: xml = ET.Element('{%s}BINVAL' % self.namespace) xml.text = bytes(base64.b64encode(value)).decode('utf-8') parent.append(xml)
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)
async def hub_send(self, command, iq_type='get', params=None, msgid=None) -> \ Optional[str]: """Send a payload request to Harmony Hub and return json response.""" # Make sure we're connected. if not await self.hub_connect(): return def result_callback(future_result): # This is done to ensure that any time out exceptions are # captured try: future_result.result() except IqTimeout: pass if not msgid: msgid = str(uuid4()) if iq_type == 'query': iq_stanza = self.make_iq_query() elif iq_type == 'set': iq_stanza = self.make_iq_set() elif iq_type == 'result': iq_stanza = self.make_iq_result() elif iq_type == 'error': iq_stanza = self.make_iq_error(id=msgid) else: iq_stanza = self.make_iq_get() iq_stanza['id'] = msgid payload = ET.Element('oa') payload.attrib['xmlns'] = DEFAULT_NS payload.attrib['mime'] = command payload_text = None for key in params: if payload_text is None: payload_text = key + '=' + str(params[key]) else: payload_text = payload_text + ':' + \ key + '=' + str(params[key]) payload.text = payload_text iq_stanza.set_payload(payload) _LOGGER.debug("%s: Sending payload: %s %s", self._ip_address, payload.attrib, payload.text) result = iq_stanza.send(timeout=1) # Add done callback to capture any timeout exceptions. result.add_done_callback(result_callback) return msgid
def set_item_attr(self, attr, value): item = self.xml.find('{http://jabber.org/protocol/muc#user}item') if item is None: item = ET.Element('{http://jabber.org/protocol/muc#user}item') self.xml.append(item) item.attrib[attr] = value return item
def fault2xml(fault): value = dict() value['faultCode'] = fault['code'] value['faultString'] = fault['string'] fault = ET.Element("fault", {'xmlns': _namespace}) fault.append(_py2xml((value))) return fault
def set_mechanisms(self, values): """ """ self.del_mechanisms() for val in values: mech = ET.Element('{%s}mechanism' % self.namespace) mech.text = val self.append(mech)
def setRoomConfig(self, room, config, ifrom=''): query = ET.Element('{http://jabber.org/protocol/muc#owner}query') x = config.getXML('submit') query.append(x) iq = self.xmpp.make_iq_set(query) iq['to'] = room iq['from'] = ifrom iq.send()
def set_chat_state(self, state): self.del_chat_state() parent = self.parent() if state in self.states: self.xml = ET.Element('{%s}%s' % (self.namespace, state)) parent.append(self.xml) elif state not in [None, '']: raise ValueError('Invalid chat state')
def setRole(self, room, nick, role): """ Change role property of a nick in a room. Typically, roles are temporary (they last only as long as you are in the room), whereas affiliations are permanent (they last across groupchat sessions). """ if role not in ('moderator', 'participant', 'visitor', 'none'): raise TypeError query = ET.Element('{http://jabber.org/protocol/muc#admin}query') item = ET.Element('item', {'role': role, 'nick': nick}) query.append(item) iq = self.xmpp.make_iq_set(query) iq['to'] = room result = iq.send() if result is False or result['type'] != 'result': raise ValueError return True
def set_room_config(self, room, config, ifrom=''): query = ET.Element('{http://jabber.org/protocol/muc#owner}query') config['type'] = 'submit' query.append(config) iq = self.xmpp.make_iq_set(query) iq['to'] = room iq['from'] = ifrom iq.send()
def peer_forward_msg(self, plugin, peer, msg, timeout=None): distribution = pkg_resources.get_distribution( plugin.__class__.__module__) iq = self.make_iq_set(ito=peer.jid) query = ET.Element("{%s}query" % PeerCommand.namespace) plugin_et = ET.Element("plugin") plugin_et.set('name', distribution.project_name) plugin_et.set('version', distribution.version) query.append(plugin_et) command_et = ET.Element("command") command_et.set('from', msg['mucnick']) command_et.text = msg['body'] query.append(command_et) iq.xml.append(query) return asyncio.ensure_future(iq.send(timeout=timeout))
def exception(self, e): """ Create and send an error reply. Typically called when an event handler raises an exception. The error's type and text content are based on the exception object's type and content. Overrides StanzaBase.exception. Arguments: e -- Exception object """ if isinstance(e, IqError): # We received an Iq error reply, but it wasn't caught # locally. Using the condition/text from that error # response could leak too much information, so we'll # only use a generic error here. reply = self.reply() reply['error']['condition'] = 'undefined-condition' reply['error']['text'] = 'External error' reply['error']['type'] = 'cancel' log.warning('You should catch IqError exceptions') reply.send() elif isinstance(e, IqTimeout): reply = self.reply() reply['error']['condition'] = 'remote-server-timeout' reply['error']['type'] = 'wait' log.warning('You should catch IqTimeout exceptions') reply.send() elif isinstance(e, XMPPError): # We raised this deliberately keep_id = self['id'] reply = self.reply(clear=e.clear) reply['id'] = keep_id reply['error']['condition'] = e.condition reply['error']['text'] = e.text reply['error']['type'] = e.etype if e.extension is not None: # Extended error tag extxml = ET.Element("{%s}%s" % (e.extension_ns, e.extension), e.extension_args) reply['error'].append(extxml) reply.send() else: # We probably didn't raise this on purpose, so send an error stanza keep_id = self['id'] reply = self.reply() reply['id'] = keep_id reply['error']['condition'] = 'undefined-condition' reply['error']['text'] = "Slixmpp got into trouble." reply['error']['type'] = 'cancel' reply.send() # log the error log.exception('Error handling {%s}%s stanza', self.namespace, self.name) # Finally raise the exception to a global exception handler self.stream.exception(e)
def make_query_roster(self, iq=None): """Create a roster query element. :param iq: Optionally use an existing stanza instead of generating a new one. """ if iq: iq['query'] = 'jabber:iq:roster' return ET.Element("{jabber:iq:roster}query")
def set_instructions(self, instructions): del self['instructions'] if instructions in [None, '']: return if not isinstance(instructions, list): instructions = instructions.split('\n') for instruction in instructions: inst = ET.Element('{%s}instructions' % self.namespace) inst.text = instruction self.xml.append(inst)