def _handle_invite(self, room_id: _RoomID, state: dict):
        """ Join rooms invited by whitelisted partners """
        if self._stop_event.ready():
            return

        self.log.debug('Got invite', room_id=room_id)
        invite_events = [
            event
            for event in state['events']
            if event['type'] == 'm.room.member' and
            event['content'].get('membership') == 'invite' and
            event['state_key'] == self._user_id
        ]
        if not invite_events:
            self.log.debug('Invite: no invite event found', room_id=room_id)
            return  # there should always be one and only one invite membership event for us
        invite_event = invite_events[0]
        sender = invite_event['sender']

        sender_join_events = [
            event
            for event in state['events']
            if event['type'] == 'm.room.member' and
            event['content'].get('membership') == 'join' and
            event['state_key'] == sender
        ]
        if not sender_join_events:
            self.log.debug('Invite: no sender join event', room_id=room_id)
            return  # there should always be one and only one join membership event for the sender
        sender_join_event = sender_join_events[0]

        user = self._get_user(sender)
        user.displayname = sender_join_event['content'].get('displayname') or user.displayname
        peer_address = validate_userid_signature(user)
        if not peer_address:
            self.log.debug(
                'Got invited to a room by invalid signed user - ignoring',
                room_id=room_id,
                user=user,
            )
            return

        if not self._address_mgr.is_address_known(peer_address):
            self.log.debug(
                'Got invited by a non-whitelisted user - ignoring',
                room_id=room_id,
                user=user,
            )
            return

        join_rules_events = [
            event
            for event in state['events']
            if event['type'] == 'm.room.join_rules'
        ]

        # room privacy as seen from the event
        private_room: bool = False
        if join_rules_events:
            join_rules_event = join_rules_events[0]
            private_room = join_rules_event['content'].get('join_rule') == 'invite'

        # we join room and _set_room_id_for_address despite room privacy and requirements,
        # _get_room_ids_for_address will take care of returning only matching rooms and
        # _leave_unused_rooms will clear it in the future, if and when needed
        room: Room = None
        last_ex: Optional[Exception] = None
        retry_interval = 0.1
        for _ in range(JOIN_RETRIES):
            try:
                room = self._client.join_room(room_id)
            except MatrixRequestError as e:
                last_ex = e
                if self._stop_event.wait(retry_interval):
                    break
                retry_interval = retry_interval * 2
            else:
                break
        else:
            assert last_ex is not None
            raise last_ex  # re-raise if couldn't succeed in retries

        if not room.listeners:
            room.add_listener(self._handle_message, 'm.room.message')

        # room state may not populated yet, so we populate 'invite_only' from event
        room.invite_only = private_room

        self._set_room_id_for_address(address=peer_address, room_id=room_id)

        self.log.debug(
            'Joined from invite',
            room_id=room_id,
            aliases=room.aliases,
            peer=to_checksum_address(peer_address),
        )
Join rooms invited by whitelisted partners