Example #1
0
        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()
Example #2
0
    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
Example #3
0
    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)
Example #4
0
    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();")
Example #5
0
    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"])