else: channelId = utils.getUniqueKey() data['room'] = channelId try: yield comet.publish('/notify/%s' % (myId), data) yield comet.publish('/notify/%s' % (recipientId), data) except Exception, e: self.setResponseCodeAndWrite(request, 200, {'error': 'The message could not be sent!'}) return yield db.insert(channelId, 'channelSubscribers', '', myId) yield db.insert(channelId, 'channelSubscribers', '', recipientId) channelSubscribers = set([myId, recipientId]) start = utils.uuid1(timestamp=time.time() - 3600).bytes cols = yield db.get_slice(myId, 'chatArchiveList', start=start, ) chatIds = [col.column.value for col in cols] participants = yield db.multiget_slice(chatIds, "chatParticipants") participants = utils.multiColumnsToDict(participants) oldTimeuuid = None chatId = None timeuuid = uuid.uuid1().bytes for col in cols: _participants = participants[col.column.value].keys() if not set(_participants).difference(channelSubscribers): chatId = col.column.value oldTimeuuid = col.column.name if not chatId: chatId = utils.getUniqueKey()
def fetchMatchingEvents(self, request, args, entityId, count=5, start=None): """Find matching events for the user, org or group for a given time range. Events are sorted by their start time and then by their end time. """ myId = args["myId"] convs = [] invitations = [] toFetchEntities = set() my_tz = timezone(args["me"].basic["timezone"]) if not start: # since we store times in UTC, find out the utc time for the user's # 00:00 hours instead of utc 00:00. utc_now = datetime.datetime.now(pytz.utc) mytz_now = utc_now.astimezone(my_tz) mytz_start = mytz_now else: mytz_start = start.replace(tzinfo=my_tz) args["start"] = mytz_start.strftime("%Y-%m-%d") timestamp = calendar.timegm(mytz_start.utctimetuple()) timeUUID = utils.uuid1(timestamp=timestamp) start = timeUUID.bytes page = args.get("page", 1) cols = yield db.get_slice(entityId, "userAgenda", start=start, count=(page*count)*2) matched_events = [col.column.value for col in cols] res = yield db.multiget_slice(matched_events, "items", ["meta"]) matched_events = utils.multiSuperColumnsToDict(res) to_sort_time_tuples = [(x, y["meta"]["event_startTime"], y["meta"]["event_endTime"]) \ for x, y in matched_events.iteritems()] sorted_time_tuples = sorted(to_sort_time_tuples, key=itemgetter(int(1), int(2))) sorted_event_ids = [x[0] for x in sorted_time_tuples] events_in_this_page = sorted_event_ids[(page-1)*count:page*count] if len(events_in_this_page) >= count: nextPage = page + 1 args.update({'nextPage': nextPage}) else: args.update({'nextPage': 0}) args["prevPage"] = page - 1 args["items"] = matched_events args["conversations"] = events_in_this_page #Now fetch all related entities, participants, owners, attendees, # invitees, groups etc for convId in events_in_this_page: entityIds = yield self.fetchData(args, convId) toFetchEntities.update(entityIds) relation = Relation(myId, []) yield relation.initGroupsList() for event, event_meta in matched_events.iteritems(): target = event_meta['meta'].get('target') if target: toFetchEntities.update(target.split(',')) entities = base.EntitySet(toFetchEntities) yield entities.fetchData() args["entities"] = entities args["relations"] = relation
def create(self, request, me, convId, richText=False): startDate = utils.getRequestArg(request, 'startDate') endDate = utils.getRequestArg(request, 'endDate') title = utils.getRequestArg(request, 'title') desc = utils.getRequestArg(request, 'desc') location = utils.getRequestArg(request, 'location') allDay = utils.getRequestArg(request, "allDay") acl = utils.getRequestArg(request, "acl", sanitize=False) isPrivate = utils.getRequestArg(request, "isPrivate") if not ((title or desc) and startDate and endDate): raise errors.MissingParams([_('Title'), _('Start date'), _('End date')]) if startDate.isdigit() and endDate.isdigit(): startDate = int(startDate)/1000 endDate = int(endDate)/1000 else: raise errors.InvalidRequest("Invalid start or end dates") if endDate < startDate: raise errors.InvalidRequest("Event end date is set in the past") # Parse invitees from the tag edit plugin values arg_keys = request.args.keys() invitees = [] for arg in arg_keys: if arg.startswith("invitee[") and arg.endswith("-a]"): rcpt = arg.replace("invitee[", "").replace("-a]", "") if rcpt != "": invitees.append(rcpt) # The owner is always invited to the event invitees.append(me.id) meta = {"event_startTime": str(startDate), "event_endTime": str(endDate)} if title: meta["event_title"] = title if desc: meta["event_desc"] = desc if location: meta["event_location"] = location if allDay: meta["event_allDay"] = '1' else: meta["event_allDay"] = '0' # Check if the invited user ids are valid res = base.EntitySet(invitees) yield res.fetchData() invitees = [x for x in res.keys() if res[x].basic["org"] == me.basic['org']] # Modify the received ACL to include those who were invited including # the owner of this item. acl = json.loads(acl) acl.setdefault("accept", {}) acl["accept"].setdefault("users", []) acl["accept"]["users"].extend(invitees) acl = json.dumps(acl) item = yield utils.createNewItem(request, self.itemType, me, richText=richText, acl=acl) item["meta"].update(meta) item["invitees"] = dict([(x, me.id) for x in invitees]) starttimeUUID = utils.uuid1(timestamp=startDate) starttimeUUID = starttimeUUID.bytes endtimeUUID = utils.uuid1(timestamp=endDate) endtimeUUID = endtimeUUID.bytes yield self.inviteUsers(request, starttimeUUID, endtimeUUID, convId, item["meta"], me.id, me.basic['org'], invitees, acl) defer.returnValue(item)
def _invite(self, request, convId=None): (appchange, script, args, myId) = yield self._getBasicArgs(request) landing = not self._ajax myOrgId = args['orgId'] convId, conv = yield utils.getValidItemId(request, "id", columns=["invitees"]) # Parse invitees from the tag edit plugin values arg_keys = request.args.keys() invitees, new_invitees = [], [] for arg in arg_keys: if arg.startswith("invitee[") and arg.endswith("-a]"): rcpt = arg.replace("invitee[", "").replace("-a]", "") if rcpt != "": invitees.append(rcpt) if myId not in conv["invitees"].keys(): raise errors.invalidRequest(_("Only those who are invited can invite others")) res = base.EntitySet(invitees) yield res.fetchData() invitees = [x for x in res.keys() if res[x].basic["org"] == myOrgId] invitees = [x for x in invitees if x not in conv["invitees"].keys()] relation = Relation(myId, []) updateConv = {"meta":{}, "invitees":{}} if myId == conv["meta"]["owner"]: #If invited by owner, add the invitees to the ACL acl = conv["meta"]["acl"] acl = pickle.loads(acl) acl.setdefault("accept", {}).setdefault("users", []) acl["accept"]["users"].extend(invitees) updateConv["meta"]["acl"] = pickle.dumps(acl) new_invitees.extend(invitees) else: for invitee in invitees: relation = Relation(invitee, []) yield relation.initGroupsList() withinAcl = utils.checkAcl(invitee, myOrgId, False, relation, conv["meta"]) if withinAcl: new_invitees.append(invitee) if new_invitees: convMeta = conv["meta"] starttime = int(convMeta["event_startTime"]) starttimeUUID = utils.uuid1(timestamp=starttime) starttimeUUID = starttimeUUID.bytes endtime = int(convMeta["event_endTime"]) endtimeUUID = utils.uuid1(timestamp=endtime) endtimeUUID = endtimeUUID.bytes updateConv["invitees"] = dict([(x, myId) for x in new_invitees]) d = yield db.batch_insert(convId, "items", updateConv) yield event.inviteUsers(request, starttimeUUID, endtimeUUID, convId, conv["meta"], myId, myOrgId, new_invitees) request.write("""$$.alerts.info('%s');""" \ %("%d people invited to this event" %len(new_invitees))) else: if not invitees: request.write("""$$.alerts.info('%s');""" \ %("Invited persons are already on the invitation list")) else: request.write("""$$.alerts.info('%s');""" \ %("Invited persons do not have access to this event")) request.write("$('#item-subactions .tagedit-listelement-old').remove();")
def _rsvp(self, request): (appchange, script, args, myId) = yield self._getBasicArgs(request) landing = not self._ajax orgId = args['orgId'] response = utils.getRequestArg(request, 'response') deferreds = [] prevResponse = "" if not response or response not in ('yes', 'maybe', 'no'): raise errors.InvalidRequest() convId, conv = yield utils.getValidItemId(request, "id", columns=["invitees"]) if not conv: raise errors.MissingParams([_("Event ID")]) if ("type" in conv["meta"] and conv["meta"]["type"] != "event"): raise errors.InvalidRequest("Not a valid event") #Find out if already stored response is the same as this one. Saves # quite a few queries rsvp_names = ["%s:%s" %(x, myId) for x in ['yes', 'no', 'maybe']] cols = yield db.get_slice(convId, "eventResponses", names=rsvp_names) if cols: prevResponse = cols[0].column.name.split(":", 1)[0] if prevResponse == response: defer.returnValue(0) starttime = int(conv["meta"]["event_startTime"]) endtime = int(conv["meta"]["event_endTime"]) starttimeUUID = utils.uuid1(timestamp=starttime) starttimeUUID = starttimeUUID.bytes endtimeUUID = utils.uuid1(timestamp=endtime) endtimeUUID = endtimeUUID.bytes #Now insert the event in the user's agenda list if the user has # never responded to this event or the user is not in the invited list. #In the second case the agenda was already updated when creating the # event if prevResponse == "" and myId not in conv["invitees"].keys(): d1 = db.insert(myId, "userAgenda", convId, starttimeUUID) d2 = db.insert(myId, "userAgenda", convId, endtimeUUID) d3 = db.insert("%s:%s" %(myId, convId), "userAgendaMap", "", starttimeUUID) d4 = db.insert("%s:%s" %(myId, convId), "userAgendaMap", "", endtimeUUID) deferreds.extend([d1, d3, d2, d4]) #Remove any old responses to this event by this user. yield db.batch_remove({'eventResponses': [convId]}, names=rsvp_names) #Now insert the user's new response. d = db.insert(convId, "eventResponses", "", "%s:%s" %(response, myId)) deferreds.append(d) if script: #Update the inline status of the rsvp status if response == "yes": rsp = _("You are attending") elif response == "no": rsp = _("You are not attending") elif response == "maybe": rsp = _("You may attend") request.write("$('#event-rsvp-status-%s').text('%s');" %(convId, rsp)) request.write("$('#conv-%s .event-join-decline').text('%s');" %(convId, rsp)) if deferreds: res = yield defer.DeferredList(deferreds) if script: args.update({"items":{convId:conv}, "convId":convId}) entityIds = yield event.fetchData(args, convId) entities = base.EntitySet(entityIds) yield entities.fetchData() args["entities"] = entities t.renderScriptBlock(request, "event.mako", "event_meta", landing, "#item-meta", "set", **args) # Push Feed Updates responseType = "E" convMeta = conv["meta"] convType = convMeta["type"] convOwnerId = convMeta["owner"] commentSnippet = convMeta["event_title"] itemId = convId convACL = convMeta["acl"] extraEntities = [convMeta["owner"]] # Importing social.feed at the beginning of the module leads to # a cyclic dependency as feed in turn imports plugins. from social.core import Feed if response == "yes": timeUUID = uuid.uuid1().bytes # Add user to the followers list of parent item yield db.insert(convId, "items", "", myId, "followers") # Update user's feed, feedItems, feed_* userItemValue = ":".join([responseType, itemId, convId, convType, convOwnerId, commentSnippet]) yield db.insert(myId, "userItems", userItemValue, timeUUID) yield db.insert(myId, "userItems_event", userItemValue, timeUUID) # Push to feed feedItemVal = "%s:%s:%s:%s" % (responseType, myId, itemId, ','.join(extraEntities)) yield Feed.push(myId, orgId, convId, conv, timeUUID, feedItemVal) elif prevResponse != "": rsvpTimeUUID = None cols = yield db.get_slice(myId, "userItems") cols = utils.columnsToDict(cols) for k, v in cols.iteritems(): if v.startswith("E"): rsvpTimeUUID = k if rsvpTimeUUID: # Remove update if user changes RSVP to no/maybe from yes. # Do not update if user had RSVPed to this event. feedUpdateVal = "%s:%s:%s:%s" % (responseType, myId, itemId, convOwnerId) yield Feed.unpush(myId, orgId, convId, conv, feedUpdateVal) # FIX: if user updates more than one item at exactly same time, # one of the updates will overwrite the other. Fix it. yield db.remove(myId, "userItems", rsvpTimeUUID) yield db.remove(myId, "userItems_event", rsvpTimeUUID) if myId != convOwnerId and response == "yes": timeUUID = uuid.uuid1().bytes yield _notify("EA", convId, timeUUID, convType=convType, convOwnerId=convOwnerId, myId=myId, me=args["me"])