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)
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}
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 {}
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)
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 {}