def request_catalog(self, jid): _task = yield response = yield _make_catalog_request(self._client.domain, jid) if response.isError(): raise StanzaError(response) catalog_node = response.getTag('catalog', namespace=Namespace.SECLABEL_CATALOG) to = catalog_node.getAttr('to') items = catalog_node.getTags('item') labels = {} default = None for item in items: label = item.getAttr('selector') if label is None: continue security = item.getTag('securitylabel', namespace=Namespace.SECLABEL) if security is None: continue try: security_label = SecurityLabel.from_node(security) except ValueError: continue labels[label] = security_label if item.getAttr('default') == 'true': default = label yield Catalog(labels=labels, default=default)
def disco_items(self, jid, node=None): _task = yield response = yield get_disco_request(Namespace.DISCO_ITEMS, jid, node) if response.isError(): raise StanzaError(response) yield parse_disco_items(response)
def get_affiliation(self, jid, affiliation): _task = yield response = yield make_affiliation_request(jid, affiliation) if response.isError(): raise StanzaError(response) room_jid = response.getFrom() query = response.getTag('query', namespace=Namespace.MUC_ADMIN) items = query.getTags('item') users_dict = {} for item in items: try: jid = JID.from_string(item.getAttr('jid')) except Exception as error: self._log.warning('Invalid JID: %s, %s', item.getAttr('jid'), error) continue users_dict[jid] = {} if item.has_attr('nick'): users_dict[jid]['nick'] = item.getAttr('nick') if item.has_attr('role'): users_dict[jid]['role'] = item.getAttr('role') reason = item.getTagData('reason') if reason: users_dict[jid]['reason'] = reason self._log.info('Affiliations received from %s: %s', room_jid, users_dict) yield AffiliationResult(jid=room_jid, users=users_dict)
def request_command_list(self, jid=None): _task = yield if jid is None: jid = self._client.get_bound_jid().bare response = yield get_disco_request(Namespace.DISCO_ITEMS, jid, node=Namespace.COMMANDS) if response.isError(): raise StanzaError(response) payload = response.getQueryPayload() if payload is None: raise MalformedStanzaError('query payload missing', response) command_list = [] for item in payload: if item.getName() != 'item': continue try: command_list.append(AdHocCommand(**item.getAttrs())) except Exception as error: raise MalformedStanzaError(f'invalid item attributes: {error}', response) yield command_list
def request_preferences(self): _task = yield response = yield _make_pref_request() if response.isError(): raise StanzaError(response) prefs = response.getTag('prefs', namespace=Namespace.MAM_2) if prefs is None: raise MalformedStanzaError('prefs node missing', response) default = prefs.getAttr('default') if default is None: raise MalformedStanzaError('default attr missing', response) always_node = prefs.getTag('always') if always_node is None: raise MalformedStanzaError('always node missing', response) always = _get_preference_jids(always_node) never_node = prefs.getTag('never') if never_node is None: raise MalformedStanzaError('never node missing', response) never = _get_preference_jids(never_node) yield MAMPreferencesData(default=default, always=always, never=never)
def make_query(self, jid, queryid=None, start=None, end=None, with_=None, after=None, max_=70): _task = yield response = yield _make_request(jid, queryid, start, end, with_, after, max_) if response.isError(): raise StanzaError(response) jid = response.getFrom() fin = response.getTag('fin', namespace=Namespace.MAM_2) if fin is None: raise MalformedStanzaError('fin node missing', response) rsm = parse_rsm(fin) if rsm is None: raise MalformedStanzaError('rsm set missing', response) complete = fin.getAttr('complete') == 'true' if not complete: if rsm.first is None or rsm.last is None: raise MalformedStanzaError('first or last element missing', response) yield MAMQueryData(jid=jid, complete=complete, rsm=rsm)
def request_entity_time(self, jid): _task = yield response = yield _make_request(jid) if response.isError(): raise StanzaError(response) yield _parse_response(response)
def request_last_activity(self, jid): _task = yield response = yield _make_request(jid) if response.isError(): raise StanzaError(response) yield _parse_response(response)
def request_software_version(self, jid): _task = yield response = yield Iq(typ='get', to=jid, queryNS=Namespace.VERSION) if response.isError(): raise StanzaError(response) yield _parse_info(response)
def set_search(self, jid, dataform, items_per_page=50, after=None): _task = yield response = yield _make_search_query(jid, dataform, items_per_page, after) if response.isError(): raise StanzaError(response) result = response.getTag('result', namespace=Namespace.MUCLUMBUS) if result is None: raise MalformedStanzaError('result node missing', response) items = result.getTags('item') if not items: yield MuclumbusResult(first=None, last=None, max=None, end=True, items=[]) set_ = result.getTag('set', namespace=Namespace.RSM) if set_ is None: raise MalformedStanzaError('set node missing', response) first = set_.getTagData('first') last = set_.getTagData('last') try: max_ = int(set_.getTagData('max')) except Exception: raise MalformedStanzaError('invalid max value', response) results = [] for item in items: jid = item.getAttr('address') name = item.getTagData('name') nusers = item.getTagData('nusers') description = item.getTagData('description') language = item.getTagData('language') is_open = item.getTag('is-open') is not None try: anonymity_mode = AnonymityMode( item.getTagData('anonymity-mode')) except ValueError: anonymity_mode = AnonymityMode.UNKNOWN results.append( MuclumbusItem(jid=jid, name=name or '', nusers=nusers or '', description=description or '', language=language or '', is_open=is_open, anonymity_mode=anonymity_mode)) yield MuclumbusResult(first=first, last=last, max=max_, end=len(items) < max_, items=results)
def execute_command(self, command, action=None, dataform=None): _task = yield if action is None: action = AdHocAction.EXECUTE attrs = { 'node': command.node, 'xmlns': Namespace.COMMANDS, 'action': action.value } if command.sessionid is not None: attrs['sessionid'] = command.sessionid response = yield _make_command(command, attrs, dataform) if response.isError(): raise StanzaError(response) command = response.getTag('command', namespace=Namespace.COMMANDS) if command is None: raise MalformedStanzaError('command node missing', response) node = command.getAttr('node') if node is None: raise MalformedStanzaError('node attribute missing', response) sessionid = command.getAttr('sessionid') if sessionid is None: raise MalformedStanzaError('sessionid attribute missing', response) status = command.getAttr('status') if status is None: raise MalformedStanzaError('status attribute missing', response) if status not in ('executing', 'completed', 'canceled'): raise MalformedStanzaError('invalid status attribute %s' % status, response) status = AdHocStatus(status) try: notes = _parse_notes(command) except ValueError as error: raise MalformedStanzaError(error, response) try: actions, default = _parse_actions(command) except ValueError as error: raise MalformedStanzaError(error, response) yield AdHocCommand(jid=response.getFrom(), name=None, node=node, sessionid=sessionid, status=status, data=command.getTag('x', namespace=Namespace.DATA), actions=actions, default=default, notes=notes)
def request_delimiter(self): _task = yield response = yield _make_request() if response.isError(): raise StanzaError(response) delimiter = response.getQuery().getTagData('roster') or None yield delimiter
def request_vcard(self, jid=None): _task = yield response = yield _make_vcard_request(jid) if response.isError(): raise StanzaError(response) vcard_node = _get_vcard_node(response) yield VCard.from_node(vcard_node)
def change_password(self, password): _task = yield response = yield _make_password_change_request(self._client.domain, self._client.username, password) if not response.isError(): yield process_response(response) else: query = response.getQuery() if query is None: raise StanzaError(response) form = get_form(query, 'jabber:iq:register:changepassword') if form is None or response.getType() != 'modify': raise StanzaError(response) raise ChangePasswordStanzaError(response, form)
def request_register_form(self, jid=None): _task = yield if jid is None: jid = self._client.domain response = yield Iq('get', Namespace.REGISTER, to=jid) if response.isError(): raise StanzaError(response) yield _parse_register_data(response)
def request_bookmarks(self): _task = yield response = yield get_private_request() if response.isError(): raise StanzaError(response) bookmarks = parse_private_bookmarks(response, self._log) for bookmark in bookmarks: self._log.info(bookmark) yield bookmarks
def request_config(self, room_jid): task = yield response = yield make_config_request(room_jid) if response.isError(): raise StanzaError(response) jid = response.getFrom() payload = response.getQueryPayload() for form in payload: if form.getNamespace() == Namespace.DATA: dataform = extend_form(node=form) self._log.info('Config form received for %s', jid) yield MucConfigResult(jid=jid, form=dataform) yield MucConfigResult(jid=jid)
def request_parameters(self, jid): task = yield response = yield _make_parameter_request(jid) if response.isError(): raise StanzaError(response) search = response.getTag('search', namespace=Namespace.MUCLUMBUS) if search is None: raise MalformedStanzaError('search node missing', response) dataform = search.getTag('x', namespace=Namespace.DATA) if dataform is None: raise MalformedStanzaError('dataform node missing', response) self._log.info('Muclumbus parameters received') yield finalize(task, extend_form(node=dataform))
def _parse_register_data(response): query = response.getTag('query', namespace=Namespace.REGISTER) if query is None: raise StanzaError(response) instructions = query.getTagData('instructions') or None data = RegisterData(instructions=instructions, form=_parse_form(response), fields_form=_parse_fields_form(query), oob_url=_parse_oob_url(query), bob_data=parse_bob_data(query)) if (data.form is None and data.fields_form is None and data.oob_url is None): raise MalformedStanzaError('invalid register response', response) return data
def request_blocking_list(self): _task = yield result = yield _make_blocking_list_request() if result.isError(): raise StanzaError(result) blocklist = result.getTag('blocklist', namespace=Namespace.BLOCKING) if blocklist is None: raise MalformedStanzaError('blocklist node missing', result) blocked = set() for item in blocklist.getTags('item'): try: jid = JID.from_string(item.getAttr('jid')) except Exception: self._log.info('Invalid JID: %s', item.getAttr('jid')) continue blocked.add(jid) self._log.info('Received blocking list: %s', blocked) yield blocked
def request_roster(self, version=None): _task = yield ver_support = self._client.features.has_roster_version() if not ver_support: version = None if ver_support and version is None: version = '' self._log.info('Roster versioning supported: %s', ver_support) response = yield _make_request(version, ver_support) if response.isError(): raise StanzaError(response) query = response.getTag('query', namespace=Namespace.ROSTER) if query is None: if not ver_support: raise MalformedStanzaError('query node missing', response) yield RosterData(None, version) pushed_items, version = self._parse_push(response, ver_support) yield RosterData(pushed_items, version)
def process_response(response): if response.isError(): raise StanzaError(response) return CommonResult(jid=response.getFrom())