Exemplo n.º 1
0
 def __temporary_save(self, cmd: GroupCommand, sender: ID) -> Optional[Content]:
     facebook = self.facebook
     from ..facebook import Facebook
     assert isinstance(facebook, Facebook), 'entity delegate error: %s' % facebook
     # check whether the owner contained in the new members
     group = cmd.group
     new_members = self.members(cmd=cmd)
     if new_members is None or len(new_members) == 0:
         raise ValueError('group command error: %s' % cmd)
     for item in new_members:
         if facebook.meta(identifier=item) is None:
             # TODO: waiting for member's meta?
             continue
         if facebook.is_owner(member=item, group=group):
             # it's a full list, save it now
             if facebook.save_members(members=new_members, identifier=group):
                 if item != sender:
                     # NOTICE: to prevent counterfeit,
                     #         query the owner for newest member-list
                     cmd = GroupCommand.query(group=group)
                     messenger = self.messenger
                     from dimsdk import Messenger
                     assert isinstance(messenger, Messenger), 'message delegate error: %s' % messenger
                     messenger.send_content(sender=None, receiver=item, content=cmd, priority=1)
             # response (no need to respond this group command)
             return None
     # NOTICE: this is a partial member-list
     #         query the sender for full-list
     return GroupCommand.query(group=group)
Exemplo n.º 2
0
 def query_group(self, group: ID, users: List[ID]) -> bool:
     now = time.time()
     last = self.__group_queries.get(group, 0)
     if (now - last) < self.EXPIRES:
         return False
     if len(users) == 0:
         return False
     self.__group_queries[group] = now
     # query from users
     cmd = GroupCommand.query(group=group)
     checking = False
     for item in users:
         if self.__send_content(content=cmd, receiver=item):
             checking = True
     return checking
Exemplo n.º 3
0
    def __process_group_message(
            self, msg: ReliableMessage) -> Optional[ReliableMessage]:
        """
        Separate group message and forward them one by one

            if members not found,
                drop this message and query group info from sender;
            if 'keys' found in group message,
                update them to cache;
                remove non-exists member from 'keys
            split group message with members, forward them

        :param msg:
        :return: ReliableMessage as result
        """
        s_msg = self.verify_message(msg=msg)
        if s_msg is None:
            # signature error?
            return None
        sender = msg.sender
        receiver = msg.receiver
        if not self.facebook.exists_member(member=sender, group=receiver):
            if not self.facebook.is_owner(member=sender, group=receiver):
                # not allow, kick it out
                cmd = GroupCommand.expel(group=receiver, member=sender)
                sender = self.facebook.current_user.identifier
                receiver = msg.sender
                env = Envelope.create(sender=sender, receiver=receiver)
                i_msg = InstantMessage.create(head=env, body=cmd)
                s_msg = self.encrypt_message(msg=i_msg)
                if s_msg is None:
                    self.error('failed to encrypt message: %s' % i_msg)
                    self.suspend_message(msg=i_msg)
                    return None
                return self.sign_message(msg=s_msg)
        members = self.facebook.members(receiver)
        if members is None or len(members) == 0:
            # members not found for this group,
            # query it from sender
            res = GroupCommand.query(group=receiver)
        else:
            # check 'keys'
            keys = msg.get('keys')
            if keys is not None:
                # remove non-exists members from 'keys'
                expel_list = []
                for item in keys:
                    if item == 'digest':
                        self.info('key digest: %s' % keys[item])
                        continue
                    m = ID.parse(identifier=item)
                    if m not in members:
                        self.info('remove non-exists member: %s' % item)
                        expel_list.append(m)
                if len(expel_list) > 0:
                    # send 'expel' command to the sender
                    cmd = GroupCommand.expel(group=receiver,
                                             members=expel_list)
                    g_messenger.send_content(sender=None,
                                             receiver=sender,
                                             content=cmd)
                # update key map
                self.__key_cache.update_keys(keys=keys,
                                             sender=sender,
                                             group=receiver)
            # split and forward group message,
            # respond receipt with success or failed list
            res = self.__split_group_message(msg=msg, members=members)
        # pack response
        if res is not None:
            sender = self.facebook.current_user.identifier
            receiver = msg.sender
            env = Envelope.create(sender=sender, receiver=receiver)
            i_msg = InstantMessage.create(head=env, body=res)
            s_msg = self.encrypt_message(msg=i_msg)
            if s_msg is None:
                self.error('failed to encrypt message: %s' % i_msg)
                self.suspend_message(msg=i_msg)
                return None
            return self.sign_message(msg=s_msg)