예제 #1
0
    def user_appears(self, user):
        if not self.chatcontext:
            return

        # find shared community conversations
        my_communities = self.myself.get('communities')
        if my_communities == None:
            my_communities = []

        user_communities = user.get('communities')
        if user_communities == None:
            user_communities = []

        addrs = []
        for c in my_communities:
            if c in user_communities and normal_traffic_mode():
                addr = 'c::%s' % c
                addrs.append(addr)

        # append private conversation address to get private conversation head
        # if it exists
        addrs.append(self.my_addr)

        request = {'t': 'request_heads', 'addrs': addrs}
        self.fetcher.fetch(user, PLUGIN_TYPE_MESSAGING, request, self.got_request_heads_reply, ctx=addrs)
예제 #2
0
    def handle_request(self, user, request):
        """ Handle incoming queries. Search through Share_Metas. """

        if request.get("t") == "msgpush":
            return self.handle_msgpush(user, request)

        if not validate(self.queryspec, request):
            warning("Invalid msgboard query: %s\n" % str(request))
            return None
        keywords = request.get("keywords")

        criteria = request.get("criteria")
        if criteria == None:
            criteria = {}
        criteria.setdefault("src", self.community.myuid)

        metas = search_metas(self.all_metas(), criteria, keywords)
        if not normal_traffic_mode():
            t = int(time())
            metas = filter(lambda meta: self.test_send_time(meta, t), metas)
            for meta in metas:
                self.set_send_time(meta, t)

        serializedmetas = []
        for meta in metas:
            serializedmetas.append(meta.serialize())

        if len(serializedmetas) == 0:
            if normal_traffic_mode():
                return {"msgs": []}
            else:
                return self.fetcher.POSTPONE_REPLY

        if self.fetcher.is_fetch_community_efficient():
            com = self.community.get_default_community()

            # Broadcast messages in bundles of three messages
            push = {"t": "msgpush"}
            for metabundle in n_lists(serializedmetas, 3):
                push["msgs"] = metabundle
                self.fetcher.fetch_community(com, self.name, push, None, ack=False)
            return self.fetcher.POSTPONE_REPLY

        return {"msgs": serializedmetas}
예제 #3
0
    def handle_icon_request(self, user, request):
        iconid = request.get('iconid')
        if iconid == None or type(iconid) != str:
            return None

        debug('Icon request from %s: %s\n' % (user.get('nick'), iconid))

        if iconid == 'user':
            icon = read_file_contents(seek_face_name(self.myself))
            version = self.myself.get('faceversion')
            limiter = self.iconfetchlimiters['user']

        elif iconid.startswith('c:'):
            cname = iconid[2:]
            if not valid_community(cname):
                return None
            if cname not in self.myself.get('communities'):
                return None
            com = self.get_ordinary_community(cname)
            if com == None:
                return None
            if com.get('myiconversion') != com.get('iconversion'):
                # Do not reply with a old version of the icon!
                return
            icon = read_file_contents(seek_community_icon_name(com))
            version = com.get('iconversion')
            limiter = self.iconfetchlimiters.get(iconid)
            if limiter == None:
                limiter = Rate_Limiter(ICON_PUSH_INTERVAL)
                self.iconfetchlimiters[iconid] = limiter
        else:
            return None

        if icon == None:
            icon = ''
        if version == None:
            version = 0

        request = {'t': 'iconpush', 'iconid': iconid, 'icon': icon, 'version': version}

        if normal_traffic_mode():
            self.fetcher.fetch(user, PLUGIN_TYPE_COMMUNITY, request, None, ack=False)
        elif limiter == None or limiter.check():
            self.fetcher.fetch_community(self.get_default_community(), PLUGIN_TYPE_COMMUNITY, request, None, ack=False)

        return {}
예제 #4
0
    def say(self, c, msg):
        parentid = ''

        # It is impossible to know which tree the user is
        # really continuing. Best guess: the one which has
        # head message, and hoping that others will also
        # start using the same tree.
        head = c.get_head()
        if head:
            parentid = head.get_msgid()

        m = Message(msg, self.my_addr, c.target_addr, parentid)

        c.add_msg(m, set_head=True)

        self.cleanup_conversation(c)

        request = {'t': 'msg', 'msg' : m.to_list()}

        ctxmsgs = []
        if self.chatcontext:
            context = []
            for i in range(MESSAGE_CONTEXT_LEN):
                if head == None:
                    break
                ctxmsgs.append(head)
                context.append({'msg': head.to_list(), 'children': []})
                head = c.get_msg(head.get_parentid())
            request['context'] = context

        ctx = (c, m, ctxmsgs)
        if c.is_community():
            community = community_from_addr(self.community, c.target_addr)
            if community != None:
                ack = normal_traffic_mode()
                if not self.fetcher.fetch_community(community, PLUGIN_TYPE_MESSAGING, request, self.got_message_reply, ctx, ack=ack):
                    m.error = True
        else:
            user = user_from_addr(self.community, c.target_addr)
            if not self.fetcher.fetch(user, PLUGIN_TYPE_MESSAGING, request, self.got_user_message_reply, ctx):
                self.notification.notify('Unable to a send message to %s' % user.tag(), True)
                m.error = True

        self.announce_new_message(c, m)
예제 #5
0
    def handle_message(self, user, msg, context):
        #if random() > 0.3:
        #    debug('Dropping message %s\n' % msg.get_msg())
        #    return

        debug('Received message %s\n' % msg.get_msg())

        if context != None:
            for item in context:
                self.got_request_reply(user, item, max_depth=0)

        msgid = msg.get_msgid()
        sender_addr = msg.get_sender_addr()
        target_addr = msg.get_target_addr()

        # validate message source and target:
        #   1. sending user uid must match with sender address
        #   2. if target is community, user and myself
        #      must be member of the community
        #   3. if target is user, it must be myself
        is_community, key, uid = decode_addr(sender_addr)
        if user.get('uid') != uid:
            warning('User \'%s\' is spoofing\n' % user.get('uid'))
            return None

        is_community, key, targetid = decode_addr(target_addr)
        if is_community:
            if not (targetid in user.get('communities') and
                    targetid in self.myself.get('communities')):
                warning('User \'%s\' is not a member of the target community\n' % user.get('uid'))
                return None
        else:
            if targetid != self.myself.get('uid'):
                return None

        # when we receive a message, the corresponding conversation
        # is identified from message as:
        #    user-to-user : from sender_addr
        #    community    : from target_addr
        if is_community:
            ckey = target_addr
        else:
            ckey = sender_addr

        # if message has no parent -> new conversation
        # if message has parent -> continue earlier conversation
        parentid = msg.get_parentid()
        c = self.get_conversation(ckey)

        # discard duplicates
        if c.has_msgid(msgid):
            return {}

        if not c.is_community():
            if user_from_addr(self.community, sender_addr) == None:
                warning('Invalid message sender (yourself or unknown user)\n')
                return None

        # get other children of parent for reply
        if parentid != '':
            other_children = c.get_children(parentid)[:]
        else:
            other_children = []

        c.add_msg(msg, set_head=True)

        self.cleanup_conversation(c)

        self.announce_new_message(c, msg)

        # if message has parent:
        #    if we don't have it -> request it and return {}
        #    if we have it -> return msg_reply with parent's other children
        # if message does not have parent -> return empty dictionary
        if self.chatcontext and parentid != '' and (not is_community or normal_traffic_mode()):
            if not c.has_msgid(parentid):
                self.request_message(user, parentid, max_depth=10)
            else:
                # XXX: Remove: 't' field after some time
                return {'t': 'msg_reply', 'parentid': parentid, 'children': other_children}

        return {}