Example #1
0
 def _compute_weights(userIds, myGroups, type):
     followers = yield db.multiget_slice(userIds, "followers", count=50)
     subscriptions = yield db.multiget_slice(userIds, "subscriptions", count=50)
     groups = yield db.multiget_slice(userIds, "entityGroupsMap")
     followers = utils.multiColumnsToDict(followers)
     subscriptions = utils.multiColumnsToDict(subscriptions)
     groups = utils.multiColumnsToDict(groups)
     for userId in followers:
         for follower in followers[userId]:
             people[follower] = people.setdefault(follower, defaultWeight) + weights[type]['follower']
     for userId in subscriptions:
         for subscription in subscriptions[userId]:
             people[subscription] = people.setdefault(subscription, defaultWeight) + weights[type]['subscription']
     for userId in groups:
         groupIds = [x.split(':', 1)[1] for x in groups[userId]]
         for groupId in groupIds:
             if groupId in myGroups:
                 people[userId] = people.setdefault(userId, defaultWeight) + weights[type]['group']
Example #2
0
    def delete(self, myId, convId, conv):
        log.debug("plugin:delete", convId)
        user_tuids = {}

        # Get the list of every user who responded to this event
        res = yield db.get_slice(convId, "eventResponses")
        attendees = [x.column.name.split(":", 1)[1] for x in res]

        # Add all the invited people of the item
        res = yield db.get_slice(convId, "items", ['invitees'])
        res = utils.supercolumnsToDict(res)
        attendees.extend(res["invitees"].keys())
        invitedPeople = res["invitees"].keys()

        log.debug("Maps", ["%s:%s"%(uId, convId) for \
                                       uId in attendees])

        # Get the Org and GroupIds if any.
        convMeta = conv["meta"]
        groupIds = convMeta["target"].split(",") if "target" in convMeta else []
        attendees.extend(groupIds+[convMeta["org"]])

        log.debug("Attendees", attendees)

        # Get the timeuuids that were inserted for this user
        res = yield db.multiget_slice(["%s:%s"%(uId, convId) for \
                                       uId in attendees], "userAgendaMap")
        res = utils.multiColumnsToDict(res)

        for k, v in res.iteritems():
            uid = k.split(":", 1)[0]
            tuids = v.keys()
            if tuids:
                user_tuids[uid] = tuids

        log.debug("userAgenda Removal", user_tuids)
        # Delete their entries in the user's list of event entries
        for attendee in user_tuids:
            yield db.batch_remove({'userAgenda': [attendee]},
                                    names=user_tuids[attendee])

        # Delete invitation entries for invited people
        invited_tuids = dict([[x, user_tuids[x]] for x in invitedPeople])
        log.debug("userAgenda Invitation Removal", invited_tuids)
        for attendee in invited_tuids:
            yield db.batch_remove({'userAgenda': ['%s:%s' %(attendee, 'I')]},
                                    names=invited_tuids[attendee])

        log.debug("eventResponses Removal", convId)
        # Delete the event's entry in eventResponses
        yield db.remove(convId, "eventResponses")

        log.debug("userAgendaMap Removal", user_tuids)
        # Delete their entries in userAgendaMap
        for attendee in user_tuids:
            yield db.batch_remove({'userAgendaMap': ["%s:%s"%(attendee, convId)]},
                                    names=user_tuids[attendee])
Example #3
0
def getGroups(me, entity, start='', count=PEOPLE_PER_PAGE):
    """get the groups of entity. (either groups of an organization
    or groups of an user)

    keyword params:
    @me:
    @entity: org/user
    start: fetch group from @start
    count: no.of groups to fetch.
    """
    toFetchCount = count + 1
    groups = {}
    groupIds = []
    myGroupsIds = []
    groupFollowers = {}
    pendingConnections = {}
    toFetchGroups = set()
    nextPageStart = ''
    prevPageStart = ''

    #TODO: list the groups in sorted order.
    cols = yield db.get_slice(entity.id, 'entityGroupsMap',
                              start=start, count=toFetchCount)
    groupIds = [x.column.name for x in cols]
    if len(groupIds) > count:
        nextPageStart = utils.encodeKey(groupIds[-1])
        groupIds = groupIds[0:count]
    toFetchGroups.update(set([y.split(':', 1)[1] for y in groupIds]))
    if entity.id == me.id:
        myGroupsIds = [x.split(':', 1)[1] for x in groupIds]
    elif groupIds:
        cols = yield db.get_slice(me.id, "entityGroupsMap", groupIds)
        myGroupsIds = [x.column.name.split(':', 1)[1] for x in cols]
    groupIds = [x.split(':', 1)[1] for x in groupIds]

    if start:
        cols = yield db.get_slice(entity.id, 'entityGroupsMap', start=start,
                                  count=toFetchCount, reverse=True)
        if len(cols) > 1:
            prevPageStart = utils.encodeKey(cols[-1].column.name)

    if toFetchGroups:
        groups = base.EntitySet(toFetchGroups)
        yield groups.fetchData()
        groupFollowers = yield db.multiget_slice(toFetchGroups, "followers",
                                                 names=[me.id])
        groupFollowers = utils.multiColumnsToDict(groupFollowers)
        columns = reduce(lambda x, y: x + y, [["GO:%s" % (x), "GI:%s" % (x)] for x in toFetchGroups])
        cols = yield db.get_slice(me.id, 'pendingConnections', columns)
        pendingConnections = utils.columnsToDict(cols)

    data = {"entities": groups, "groupIds": groupIds,
            "pendingConnections": pendingConnections,
            "myGroups": myGroupsIds, "groupFollowers": groupFollowers,
            "nextPageStart": nextPageStart, "prevPageStart": prevPageStart}
    defer.returnValue(data)
Example #4
0
def getManagedGroups(me, start, count=PEOPLE_PER_PAGE):
    """get all groups managed by me

    Keyword params:
    @me:
    @start: get groups from @start.
    @count: no.of groups to be fetched.
    """
    groups = {}
    groupIds = []
    myGroupsIds = []
    nextPageStart = ''
    prevPageStart = ''
    toFetchCount = count + 1
    toFetchGroups = set()
    groupFollowers = {}
    pendingConnections = {}

    try:
        cols = yield db.get_slice(me.id, "entities",
                                  super_column='adminOfGroups',
                                  start=start, count=toFetchCount)
        groupIds = [x.column.name for x in cols]
        toFetchGroups.update(set(groupIds))
        myGroupsIds = groupIds
        if len(groupIds) > count:
            nextPageStart = utils.encodeKey(groupIds[-1])
            groupIds = groupIds[0:count]
    except ttypes.NotFoundException:
        pass

    if start:
        cols = yield db.get_slice(me.id, "entities",
                                  super_column='adminOfGroups', start=start,
                                 count=toFetchCount, reverse=True)
        if len(cols) > 1:
            prevPageStart = utils.encodeKey(cols[-1].column.name)

    if toFetchGroups:
        groups = base.EntitySet(toFetchGroups)
        yield groups.fetchData()
        groupFollowers = yield db.multiget_slice(toFetchGroups, "followers", names=[me.id])
        groupFollowers = utils.multiColumnsToDict(groupFollowers)
        columns = reduce(lambda x, y: x + y, [["GO:%s" % (x), "GI:%s" % (x)] for x in toFetchGroups])
        cols = yield db.get_slice(me.id, 'pendingConnections', columns)
        pendingConnections = utils.columnsToDict(cols)

    data = {"entities": groups, "groupIds": groupIds,
            "pendingConnections": pendingConnections,
            "myGroups": myGroupsIds, "groupFollowers": groupFollowers,
            "nextPageStart": nextPageStart, "prevPageStart": prevPageStart}
    defer.returnValue(data)
Example #5
0
def responses(myId, itemId, item, start=''):
    toFetchEntities = set()
    itemResponses = yield db.get_slice(itemId, "itemResponses",
                                       start=start, reverse=True,
                                       count=constants.COMMENTS_PER_PAGE + 1)

    nextPageStart = itemResponses[-1].column.name\
                    if len(itemResponses) > constants.COMMENTS_PER_PAGE\
                    else None
    itemResponses = itemResponses[:-1] \
                    if len(itemResponses) > constants.COMMENTS_PER_PAGE\
                    else itemResponses
    responseKeys = []
    for response in itemResponses:
        userKey, responseKey = response.column.value.split(":")
        responseKeys.append(responseKey)
        toFetchEntities.add(userKey)
    responseKeys.reverse()
    entities = base.EntitySet(toFetchEntities)

    d3 = db.multiget_slice(responseKeys + [itemId], "itemLikes", [myId])
    d2 = db.multiget_slice(responseKeys + [itemId], "items", ["meta", "attachments"])
    d1 = entities.fetchData()

    fetchedItems = yield d2
    myLikes = yield d3
    yield d1

    fetchedItems = utils.multiSuperColumnsToDict(fetchedItems)
    fetchedLikes = utils.multiColumnsToDict(myLikes)

    # Do some error correction/consistency checking to ensure that the
    # response items actually exist. I don't know of any reason why these
    # items may not exist.
    missingIds = [x for x, y in fetchedItems.items() if not y]
    if missingIds:
        yield _cleanupMissingComments(itemId, missingIds, itemResponses)

    ret = {'items': fetchedItems, 'entities': entities,
            'myLikes': myLikes, 'responses': {itemId: responseKeys}}
    if nextPageStart:
        ret['oldest'] = utils.encodeKey(nextPageStart)
    defer.returnValue(ret)
Example #6
0
    def _getUserItems(self, request, userId, start='', count=10):
        authinfo = request.getSession(IAuthInfo)
        myId = authinfo.username
        myOrgId = authinfo.organization

        toFetchItems = set()
        toFetchEntities = set()
        toFetchTags = set()
        toFetchResponses = set()
        toFetchCount = count + 1
        toFetchStart = utils.decodeKey(start) if start else ''
        fetchedUserItem = []
        responses = {}
        convs = []
        userItemsRaw = []
        userItems = []
        reasonStr = {}
        timestamps = {}
        items = {}
        nextPageStart = None
        args = {'myId': myId}

        relation = Relation(myId, [])
        yield relation.initGroupsList()

        toFetchEntities.add(userId)

        while len(convs) < toFetchCount:
            cols = yield db.get_slice(userId, "userItems", start=toFetchStart,
                                      reverse=True, count=toFetchCount)
            tmpIds = []
            for col in cols:
                convId = col.column.value.split(":")[2]
                if convId not in tmpIds and convId not in convs:
                    tmpIds.append(convId)
            (filteredConvs, deletedConvs) = yield utils.fetchAndFilterConvs\
                                        (tmpIds, relation, items, myId, myOrgId)
            for col in cols[0:count]:
                convId = col.column.value.split(":")[2]
                if len(convs) == count or len(fetchedUserItem) == count*2:
                    nextPageStart = col.column.name
                    break
                if convId not in filteredConvs and convId not in convs:
                    continue
                fetchedUserItem.append(col)
                if convId not in convs:
                    convs.append(convId)
            if len(cols) < toFetchCount or nextPageStart:
                break
            if cols:
                toFetchStart = cols[-1].column.name
        if nextPageStart:
            nextPageStart = utils.encodeKey(nextPageStart)

        for col in fetchedUserItem:
            value = tuple(col.column.value.split(":"))
            timestamps[value] = col.column.timestamp/1e6
            rtype, itemId, convId, convType, convOwnerId, commentSnippet = value
            commentSnippet = """<span class="snippet">"%s"</span>""" %(_(commentSnippet))
            toFetchEntities.add(convOwnerId)
            if rtype == 'I':
                toFetchItems.add(convId)
                toFetchResponses.add(convId)
                userItems.append(value)
            elif rtype == "L" and itemId == convId and convOwnerId != userId:
                reasonStr[value] = _("liked %s's %s")
                userItems.append(value)
            elif rtype == "L"  and convOwnerId != userId:
                r = "answer" if convType == 'question' else 'comment'
                reasonStr[value] = _("liked") + " %s " %(commentSnippet) + _("%s "%r) + _("on %s's %s")
                userItems.append(value)
            elif rtype in ["C", 'Q'] and convOwnerId != userId:
                reasonStr[value] = "%s"%(commentSnippet) + _(" on %s's %s")
                userItems.append(value)

        itemResponses = yield db.multiget_slice(toFetchResponses, "itemResponses",
                                                count=2, reverse=True)
        for convId, comments in itemResponses.items():
            responses[convId] = []
            for comment in comments:
                userId_, itemKey = comment.column.value.split(':')
                if itemKey not in toFetchItems:
                    responses[convId].insert(0,itemKey)
                    toFetchItems.add(itemKey)
                    toFetchEntities.add(userId_)

        items = yield db.multiget_slice(toFetchItems, "items", ["meta", "tags", "attachments"])
        items = utils.multiSuperColumnsToDict(items)
        args["items"] = items
        extraDataDeferreds = []

        for convId in convs:
            if convId not in items:
                continue

            meta = items[convId]["meta"]
            itemType = meta["type"]
            toFetchEntities.add(meta["owner"])
            if "target" in meta:
                toFetchEntities.update(meta["target"].split(','))

            toFetchTags.update(items[convId].get("tags", {}).keys())

            if itemType in plugins:
                d =  plugins[itemType].fetchData(args, convId)
                extraDataDeferreds.append(d)

        result = yield defer.DeferredList(extraDataDeferreds)
        for success, ret in result:
            if success:
                toFetchEntities.update(ret)

        entities = base.EntitySet(toFetchEntities)
        yield entities.fetchData()

        tags = {}
        if toFetchTags:
            userOrgId = entities[userId].basic["org"]
            fetchedTags = yield db.get_slice(userOrgId, "orgTags", toFetchTags)
            tags = utils.supercolumnsToDict(fetchedTags)

        fetchedLikes = yield db.multiget(toFetchItems, "itemLikes", myId)
        myLikes = utils.multiColumnsToDict(fetchedLikes)

        data = {"entities": entities, "reasonStr": reasonStr,
                "tags": tags, "myLikes": myLikes, "userItems": userItems,
                "responses": responses, "nextPageStart": nextPageStart,
                "timestamps": timestamps }
        del args['myId']
        args.update(data)
        defer.returnValue(args)
Example #7
0
    def _renderChatArchives(self, request):
        (appchange, script, args, myId) = yield self._getBasicArgs(request)
        orgId = args['orgId']
        landing = not self._ajax
        start = utils.getRequestArg(request, 'start') or ''
        start = utils.decodeKey(start)
        count = constants.CHATS_PER_PAGE

        if script and landing:
            t.render(request, "chat.mako", **args)

        if appchange and script:
            t.renderScriptBlock(request, "chat.mako", "layout",
                                landing, "#mainbar", "set", **args)

        chats = {}
        chatParticipants = {}
        prevPageStart = ''
        nextPageStart = ''
        cols = yield db.get_slice(myId, "chatArchiveList", start=start,
                                  count=count + 1, reverse=True)
        chatIds = [col.column.value for col in cols]
        if len(cols) == count + 1:
            chatIds = chatIds[:count]
            nextPageStart = utils.encodeKey(cols[-1].column.name)
        cols = yield db.get_slice(myId, "chatArchiveList", start=start,
                                  count=count + 1)
        if len(cols) > 1 and start:
            prevPageStart = utils.encodeKey(cols[-1].column.name)
        if chatIds:
            cols = yield db.multiget_slice(chatIds, "chatLogs", reverse=False)
            chats = OrderedDict()
            for chatId in cols:
                chats[chatId] = []
                for col in cols[chatId]:
                    entityId, comment = col.column.value.split(':', 1)
                    chats[chatId] = (entityId, comment, col.column.timestamp / 1e6)
        participants = yield db.multiget_slice(chatIds, "chatParticipants")
        participants = utils.multiColumnsToDict(participants)
        entityIds = set([])
        for chatId in participants:
            entityIds.update(participants[chatId])
        entities = base.EntitySet(entityIds)
        yield entities.fetchData()
        entities.update(args['me'])
        args.update({'chatParticipants': participants,
                      'entities': entities,
                      'chats': chats,
                      'chatIds': chatIds,
                      'nextPageStart': nextPageStart,
                      'prevPageStart': prevPageStart,
                      'view': 'list',
                      'menuId': 'chats'})

        if script:
            onload = """
                         $$.menu.selectItem('chats');
                     """
            t.renderScriptBlock(request, "chat.mako", "chatList",
                                landing, '.center-contents', "set", True,
                                handlers={"onload": onload}, **args)
        else:
            t.render(request, "chat.mako", **args)
Example #8
0
                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()
            for userId in channelSubscribers:
                yield db.insert(chatId, "chatParticipants", '', userId)
        for userId in channelSubscribers:
            yield db.insert(chatId, "chatLogs", '%s:%s' % (myId, comment),
                            timeuuid)
Example #9
0
    def _listGroups(self, request):
        appchange, script, args, myId = yield self._getBasicArgs(request)
        landing = not self._ajax
        me = args['me']

        viewType = utils.getRequestArg(request, 'type') or 'myGroups'
        start = utils.getRequestArg(request, 'start') or ''
        start = utils.decodeKey(start)

        viewTypes = ['myGroups', 'allGroups', 'adminGroups', 'pendingRequests', 'invitations']
        viewType = 'myGroups' if viewType not in viewTypes else viewType

        args["menuId"] = "groups"
        args['viewType'] = viewType

        cols = yield db.get_slice(myId, "entities", super_column='adminOfGroups')
        managedGroupIds = [col.column.name for col in cols]

        ##TODO: can we use getLatestCounts instead of fetching pendingConnections?
        cols = yield db.multiget_slice(managedGroupIds, "pendingConnections", count=1)
        cols = utils.multiColumnsToDict(cols)

        showPendingRequestsTab = sum([len(cols[groupId]) for groupId in cols]) > 0
        args["showPendingRequestsTab"] = showPendingRequestsTab

        if viewType == 'pendingRequests' and not showPendingRequestsTab:
            viewType = 'myGroups'
            args["viewType"] = viewType

        cols = yield db.get_slice(myId, "pendingConnections", start="GI:", count=1)
        args["showInvitationsTab"] = bool(len([col for col in cols if col.column.name.startswith('GI:')]))

        if viewType == 'invitations' and not args["showInvitationsTab"]:
            viewType = 'myGroups'
            args['viewType'] = viewType

        counts = yield utils.getLatestCounts(request, False)
        groupRequestCount = args["groupRequestCount"] = counts["groups"]

        if script and landing:
            t.render(request, "groups.mako", **args)

        if script and appchange:
            t.renderScriptBlock(request, "groups.mako", "layout",
                                landing, "#mainbar", "set", **args)

        if viewType not in ['pendingRequests', 'invitations']:
            if viewType == 'myGroups':
                data = yield Group.getGroups(me, me, start)
            elif viewType == 'allGroups':
                data = yield Group.getGroups(me, args['org'], start)
            else:
                data = yield Group.getManagedGroups(me, start)
            args.update(data)

        elif viewType == 'pendingRequests':
            data = yield Group.getGroupRequests(me, start)
            args.update(data)
            args['tab'] = 'pending'
        elif viewType == 'invitations':
            data = yield Group.getAllInvitations(me, start)
            args.update(data)

        if script:
            t.renderScriptBlock(request, "groups.mako", "titlebar",
                                landing, "#titlebar", "set", **args)
            t.renderScriptBlock(request, "groups.mako", "viewOptions",
                                landing, "#groups-view", "set", args=[viewType],
                                showPendingRequestsTab=showPendingRequestsTab,
                                showInvitationsTab=args['showInvitationsTab'],
                                groupRequestCount=groupRequestCount)
            if viewType == "pendingRequests":
                t.renderScriptBlock(request, "groups.mako", "allPendingRequests",
                                    landing, "#groups-wrapper", "set", **args)
            else:
                t.renderScriptBlock(request, "groups.mako", "listGroups",
                                    landing, "#groups-wrapper", "set", **args)
            t.renderScriptBlock(request, "groups.mako", "paging",
                                landing, "#groups-paging", "set", **args)

        if not script:
            t.render(request, "groups.mako", **args)
Example #10
0
    entities_d = entities.fetchData()

    # Results of previously initiated fetches (items, tags, entities, likes)
    fetchedItems = yield items_d
    items.update(utils.multiSuperColumnsToDict(fetchedItems))

    # Filter out any deleted comments from the fetched items.
    for itemId, itemVal in items.items():
        if itemVal.get('meta', {}).get('state', None) == 'deleted':
            del items[itemId]

    fetchedTags = yield tags_d
    tags.update(utils.supercolumnsToDict(fetchedTags))

    fetchedMyLikes = yield myLikes_d
    myLikes.update(utils.multiColumnsToDict(fetchedMyLikes))

    #fetchedEntities = yield entities_d
    #entities.update(utils.multiSuperColumnsToDict(fetchedEntities))
    yield entities_d
    data['entities'].update(entities)


    # Time to build reason strings (and reason userIds)
    if getReasons:
        reasonStr = {}
        reasonUserIds = {}

        for convId in convReasonUpdates.keys():
            if convId not in convIds:
                continue
Example #11
0
    def postFeedback(self, request):
        """creates a feedback item with feedback, feedback-{mood} tags.
        Push item to feeback, feedback-{mood} tag followers.
        Note: Item is owned by feedback-domain/synovel.com, not user sending
        the feedback. Only users of feedback-domain/synovel.com can access
        the item.
        """
        comment = utils.getRequestArg(request, 'comment')
        mood = utils.getRequestArg(request, 'mood')
        if not mood or not comment:
            raise errors.MissingParams([_("Feedback")])

        authInfo = request.getSession(IAuthInfo)
        myId = authInfo.username
        orgId = authInfo.organization

        tagName = 'feedback'
        moodTagName = 'feedback-' + mood

        feedbackDomain = config.get('Feedback', 'Domain') or 'synovel.com'
        cols = yield db.get_slice(feedbackDomain, 'domainOrgMap')
        if not cols:
            raise errors.ConfigurationError("feedbackDomain is invalid!")

        # Only one org exists per domain
        synovelOrgId = cols[0].column.name

        tagId, tag = yield tags.ensureTag(request, tagName, synovelOrgId)
        moodTagId, moodTag = yield tags.ensureTag(request, moodTagName,
                                                  synovelOrgId)

        # Anyone in synovel can receive feedback.
        acl = {'accept': {'orgs': [synovelOrgId]}}
        acl = json.dumps(acl)
        synovelOrg = base.Entity(synovelOrgId)
        yield synovelOrg.fetchData()
        # createNewItem expects an entity object with has org in basic info.
        # organizations wont have 'org' set.
        synovelOrg.basic['org'] = synovelOrgId

        item = yield utils.createNewItem(request, 'feedback', synovelOrg,
                                         acl, subType=mood)
        item['meta']['org'] = synovelOrgId
        item['meta']['userId'] = myId
        item['meta']['userOrgId'] = orgId
        item['meta']['comment'] = comment
        item['tags'] = {tagId: synovelOrgId, moodTagId: synovelOrgId}

        itemId = utils.getUniqueKey()

        tagItemCount = int(tag['itemsCount'])
        moodTagItemCount = int(moodTag['itemsCount'])
        if tagItemCount % 10 == 7:
            tagItemCount = yield db.get_count(tagId, "tagItems")
        if moodTagItemCount % 10 == 7:
            moodTagItemCount = yield db.get_count(moodTagId, "tagItems")

        tagItemCount += 1
        moodTagItemCount += 1

        # Finally save the feedback
        yield db.batch_insert(itemId, "items", item)
        yield db.insert(tagId, "tagItems", itemId, item["meta"]["uuid"])
        yield db.insert(moodTagId, "tagItems", itemId, item["meta"]["uuid"])
        yield db.insert(synovelOrgId, "orgTags", str(tagItemCount),
                        "itemsCount", tagId)
        yield db.insert(synovelOrgId, "orgTags", str(moodTagItemCount),
                        "itemsCount", moodTagId)

        cols = yield db.multiget_slice([tagId, moodTagId], "tagFollowers")
        followers = utils.multiColumnsToDict(cols)
        followers = set(followers[tagId].keys() + followers[moodTagId].keys())

        value = {"feed": {item['meta']['uuid']: itemId}}
        muts = dict([(x, value) for x in followers])
        if muts:
            yield db.batch_mutate(muts)
Example #12
0
def _update_suggestions(request, relation=None):
    authinfo = request.getSession(IAuthInfo)
    myId = authinfo.username
    orgId = authinfo.organization
    weights = {'group': {'follower': 15, 'subscription': 40, 'group': 30},
               'follower': {'follower': 9, 'subscription': 24, 'group': 15},
               'subscription': {'follower': 24, 'subscription': 64, 'group': 40}}
    defaultWeight = 1
    people = {}

    @defer.inlineCallbacks
    def _compute_weights(userIds, myGroups, type):
        followers = yield db.multiget_slice(userIds, "followers", count=50)
        subscriptions = yield db.multiget_slice(userIds, "subscriptions", count=50)
        groups = yield db.multiget_slice(userIds, "entityGroupsMap")
        followers = utils.multiColumnsToDict(followers)
        subscriptions = utils.multiColumnsToDict(subscriptions)
        groups = utils.multiColumnsToDict(groups)
        for userId in followers:
            for follower in followers[userId]:
                people[follower] = people.setdefault(follower, defaultWeight) + weights[type]['follower']
        for userId in subscriptions:
            for subscription in subscriptions[userId]:
                people[subscription] = people.setdefault(subscription, defaultWeight) + weights[type]['subscription']
        for userId in groups:
            groupIds = [x.split(':', 1)[1] for x in groups[userId]]
            for groupId in groupIds:
                if groupId in myGroups:
                    people[userId] = people.setdefault(userId, defaultWeight) + weights[type]['group']

    if not relation:
        relation = Relation(myId, [])
        yield defer.DeferredList([relation.initSubscriptionsList(),
                                  relation.initFollowersList(),
                                  relation.initGroupsList()])
    if relation.followers:
        yield _compute_weights(relation.followers, relation.groups, 'follower')
    if relation.subscriptions:
        yield _compute_weights(relation.subscriptions, relation.groups, 'subscription')
    if relation.groups:
        groupMembers = yield db.multiget_slice(relation.groups, "groupMembers", count=20)
        groupMembers = utils.multiColumnsToDict(groupMembers)
        for groupId in groupMembers:
            yield  _compute_weights(groupMembers[groupId], relation.groups, 'group')

    cols = yield db.get_slice(orgId, "orgUsers", count=100)
    for col in cols:
        userId = col.column.name
        if userId not in people:
            people[userId] = people.setdefault(userId, 0) + defaultWeight

    suggestions = {}
    for userId in people:
        if isValidSuggestion(myId, userId, relation):
            suggestions.setdefault(people[userId], []).append(userId)

    yield db.remove(myId, "suggestions")
    weights_userIds_map = {}
    format = '>l'
    for weight in suggestions:
        key = struct.pack(format, weight)
        weights_userIds_map[key] = ' '.join(suggestions[weight])
    if weights_userIds_map:
        yield db.batch_insert(myId, "suggestions", weights_userIds_map)
Example #13
0
def _sendInvitations(myOrgUsers, otherOrgUsers, me, myId, myOrg):
    rootUrl = config.get('General', 'URL')
    brandName = config.get('Branding', 'Name')
    senderName = me.basic["name"]
    senderOrgName = myOrg.basic["name"]
    senderAvatarUrl = utils.userAvatar(myId, me, "medium")
    sentUsers = []
    blockedUsers = []
    existingUsers = []

    myOrgSubject = "%s invited you to %s" % (senderName, brandName)
    myOrgBody = "Hi,\n\n"\
                "%(senderName)s has invited you to %(senderOrgName)s network on %(brandName)s.\n"\
                "To activate your account please visit: %(activationUrl)s.\n\n"
    otherOrgSubject = "%s invited you to %s" % (senderName, brandName)
    otherOrgBody = "Hi,\n\n"\
                   "%(senderName)s has invited you to try %(brandName)s.\n"\
                   "To activate your account please visit: %(activationUrl)s.\n\n"

    signature = "Flocked.in Team.\n\n\n\n"\
                "--\n"\
                "To block invitations from %(senderName)s visit %(blockSenderUrl)s\n"\
                "To block all invitations from %(brandName)s visit %(blockAllUrl)s"

    blockSenderTmpl = "%(rootUrl)s/signup/blockSender?email=%(emailId)s&token=%(token)s"
    blockAllTmpl = "%(rootUrl)s/signup/blockAll?email=%(emailId)s&token=%(token)s"
    activationTmpl = "%(rootUrl)s/signup?email=%(emailId)s&token=%(token)s"

    # Combine all users.
    myOrgUsers.extend(otherOrgUsers)

    # Ensure that the users do not already exist and that the users are
    # not in the doNotSpam list (for this sender or globally)
    d1 = db.multiget(myOrgUsers, "userAuth", "user")
    d2 = db.multiget_slice(myOrgUsers, "doNotSpam", [myId, '*'])
    existing = yield d1
    existing = utils.multiColumnsToDict(existing)
    doNotSpam = yield d2
    doNotSpam = utils.multiColumnsToDict(doNotSpam)

    deferreds = []
    for emailId in myOrgUsers:
        if emailId in existing and existing[emailId]:
            existingUsers.append(emailId)
            continue

        token = utils.getRandomKey()

        # Add invitation to the database
        localpart, domainpart = emailId.split('@')
        deferreds.append(db.insert(domainpart, "invitations", myId, token, emailId))
        deferreds.append(db.insert(myId, "invitationsSent", '', emailId))

        # Mail the invitation if everything is ok.
        if emailId in doNotSpam and doNotSpam[emailId]:
            blockedUsers.append(emailId)
            continue

        activationUrl = activationTmpl % locals()
        blockAllUrl = blockAllTmpl % locals()
        blockSenderUrl = blockSenderTmpl % locals()
        sameOrg = False if emailId in otherOrgUsers else True
        if not sameOrg:
            subject = otherOrgSubject
            textBody = (otherOrgBody + signature) % locals()
        else:
            subject = myOrgSubject
            textBody = (myOrgBody + signature) % locals()

        # XXX: getBlock blocks the application for disk reads when reading template
        htmlBody = t.getBlock("emails.mako", "invite", **locals())
        deferreds.append(utils.sendmail(emailId, subject, textBody, htmlBody))
        sentUsers.append(emailId)

    yield defer.DeferredList(deferreds)
    defer.returnValue((sentUsers, blockedUsers, existingUsers))
Example #14
0
    def renderItem(self, request, toFeed=False):
        (appchange, script, args, myId) = yield self._getBasicArgs(request)
        landing = not self._ajax
        myOrgId = args["orgId"]

        convId, conv = yield utils.getValidItemId(request, "id", columns=['tags'])
        itemType = conv["meta"].get("type", None)

        if 'parent' in conv['meta']:
            raise errors.InvalidItem('conversation', convId)

        start = utils.getRequestArg(request, "start") or ''
        start = utils.decodeKey(start)

        args['convId'] = convId
        args['isItemView'] = True
        args['items'] = {convId: conv}
        meta = conv["meta"]
        owner = meta["owner"]

        relation = Relation(myId, [])
        yield defer.DeferredList([relation.initGroupsList(),
                                  relation.initSubscriptionsList()])
        args["relations"] = relation

        if script and landing:
            t.render(request, "item.mako", **args)

        if script and appchange:
            t.renderScriptBlock(request, "item.mako", "layout",
                                landing, "#mainbar", "set", **args)

        args["entities"] = {}
        toFetchEntities = set()
        toFetchTags = set(conv.get("tags", {}).keys())

        plugin = plugins[itemType] if itemType in plugins else None
        if plugin:
            entityIds = yield plugin.fetchData(args)
            toFetchEntities.update(entityIds)

        toFetchEntities.add(conv['meta']['owner'])
        if "target" in conv["meta"]:
            toFetchEntities.update(conv['meta']['target'].split(','))

        if conv['meta']['owner'] not in toFetchEntities:
            toFetchEntities.add(conv['meta']['owner'])
        entities = base.EntitySet(toFetchEntities)
        yield entities.fetchData()
        args["entities"] = entities

        renderers = []

        if script:
            t.renderScriptBlock(request, "item.mako", "conv_root",
                                landing, "#conv-root-%s > .conv-summary" % (convId),
                                "set", **args)

        convOwner = args["items"][convId]["meta"]["owner"]
        args["ownerId"] = convOwner
        if script:
            if itemType != "feedback":
                t.renderScriptBlock(request, "item.mako", "conv_owner",
                                    landing, "#conv-avatar-%s" % convId,
                                    "set", **args)
            else:
                feedbackType = conv['meta']['subType']
                t.renderScriptBlock(request, "item.mako", "feedback_icon",
                                    landing, "#conv-avatar-%s" % convId,
                                    "set", args=[feedbackType])

        # A copy of this code for fetching comments is present in _responses
        # Most changes here may need to be done there too.
        itemResponses = yield db.get_slice(convId, "itemResponses",
                                           start=start, reverse=True,
                                           count=constants.COMMENTS_PER_PAGE + 1)
        nextPageStart = itemResponses[-1].column.name\
                        if len(itemResponses) > constants.COMMENTS_PER_PAGE\
                        else None
        itemResponses = itemResponses[:-1] \
                        if len(itemResponses) > constants.COMMENTS_PER_PAGE\
                        else itemResponses
        responseKeys = []
        for response in itemResponses:
            userKey, responseKey = response.column.value.split(":")
            responseKeys.append(responseKey)
            toFetchEntities.add(userKey)
        responseKeys.reverse()

        subscriptions = list(relation.subscriptions)
        likes = yield db.get_slice(convId, "itemLikes", subscriptions) \
                            if subscriptions else defer.succeed([])
        toFetchEntities.update([x.column.name for x in likes])
        entities = base.EntitySet(toFetchEntities)
        d1 = entities.fetchData()
        d2 = db.multiget_slice(responseKeys, "items", ["meta", "attachments"])
        d3 = db.multiget_slice(responseKeys + [convId], "itemLikes", [myId])
        d4 = db.get_slice(myOrgId, "orgTags", toFetchTags)\
                                    if toFetchTags else defer.succeed([])

        yield d1
        fetchedItems = yield d2
        myLikes = yield d3
        fetchedTags = yield d4

        fetchedItems = utils.multiSuperColumnsToDict(fetchedItems)
        myLikes = utils.multiColumnsToDict(myLikes)
        fetchedTags = utils.supercolumnsToDict(fetchedTags)

        # Do some error correction/consistency checking to ensure that the
        # response items actually exist. I don't know of any reason why these
        # items may not exist.
        missingIds = [x for x, y in fetchedItems.items() if not y]
        if missingIds:
            yield self._cleanupMissingComments(convId, missingIds, itemResponses)

        args["items"].update(fetchedItems)
        args["entities"].update(entities)
        args["myLikes"] = myLikes
        args["tags"] = fetchedTags
        args["responses"] = {convId: responseKeys}
        if nextPageStart:
            args["oldest"] = utils.encodeKey(nextPageStart)

        if script:
            t.renderScriptBlock(request, "item.mako", 'conv_footer',
                                landing, '#item-footer-%s' % convId,
                                'set', **args)
            t.renderScriptBlock(request, "item.mako", 'conv_tags',
                                landing, '#conv-tags-wrapper-%s' % convId, 'set',
                                handlers={"onload": "$('#conv-meta-wrapper-%s').removeClass('no-tags')" % convId} if toFetchTags else None, **args)
            t.renderScriptBlock(request, "item.mako", 'conv_comments',
                                landing, '#conv-comments-wrapper-%s' % convId, 'set', **args)
            t.renderScriptBlock(request, "item.mako", 'conv_comment_form',
                                landing, '#comment-form-wrapper-%s' % convId, 'set',
                                True, handlers={"onload": "(function(obj){$$.convs.load(obj);})(this);"}, **args)

            numLikes = int(conv["meta"].get("likesCount", "0"))
            if numLikes:
                numLikes = int(conv["meta"].get("likesCount", "0"))
                iLike = myId in args["myLikes"].get(convId, [])
                t.renderScriptBlock(request, "item.mako", 'conv_likes',
                                    landing, '#conv-likes-wrapper-%s' % convId, 'set',
                                    args=[convId, numLikes, iLike, [x.column.name for x in likes]],
                                    entities=args['entities'])

        if plugin and hasattr(plugin, 'renderItemSideBlock'):
            plugin.renderItemSideBlock(request, landing, args)

        if script and landing:
            request.write("</body></html>")

        if not script:
            t.render(request, "item.mako", **args)