Ejemplo n.º 1
0
def notify_on_attendee(event_id, user_id):
    try:
        event = Event.find(event_id)
        user = User.find(user_id)
        if event.owner is None:
            return
    except DoesNotExist:
        return

    if event.is_expired or not user.is_attending(event):
        return

    targets = [5, 10, 20, 30, 50, 75, 100, 150, 200, 250, 300, 350, 400, 450, 500]
    num_attending = get_num_attending(event_id)
    target = next(reversed([t for t in targets if t <= num_attending]), None)

    if target is None:
        return

    rl_key = 'notify:event_creators:{}:{}:{}'.format(event.id, event.owner_id, target)
    with rate_limit(rl_key, event.expires) as limited:
        if not limited:
            notification = Notification({
                'user_id': event.owner_id,
                'type': 'system',
                'navigate': '/events/{}'.format(event_id),
                'badge': 1,
                'message': '{} people are going to your event {}'.format(
                    num_attending, event.name.encode('utf-8'))
            }).save()

            send_notification_push.delay(notification.to_primitive())
Ejemplo n.º 2
0
    def get(self, headers):
        user = g.user
        group = g.group

        query = self.select().group(group)
        query = query.min(epoch(group.get_day_end() - timedelta(days=8)))
        query = query.max(epoch(group.get_day_end() + timedelta(hours=4)))
        count, page, events = query.execute()

        if count == 0 and group.status == 'initializing':
            tries = int(request.args.get('tries', 0))
            if tries < 5:
                sleep(1)  # clients seem to not obey Retry-After, so artificially delay
                request_arguments = request.args.copy().to_dict()
                request_arguments['tries'] = tries
                response = redirect('%s?%s' % (request.path, url_encode(request_arguments)))
                response.headers.add('Retry-After', 1)
                return response
            else:
                # return without "headers" so this response isn't cached
                return self.serialize_list(self.model, events, count, page), 200

        attending_id = g.user.get_attending_id()
        if attending_id:
            try:
                attending = Event.find(attending_id)
                if attending in events:
                    events.remove(attending)
                if 'page' not in request.args:
                    events.insert(0, attending)
                    attending.current_user_attending = True
            except DoesNotExist:
                logger.warn('Event {} not found'.format(attending_id))

        return self.serialize_list(self.model, events, count, page), 200, headers
Ejemplo n.º 3
0
def test_private_event():
    from server.models.event import Event, EventAttendee
    from server.models.user import User

    with client() as c:
        user1 = User.find(key='test')
        user2 = User.find(key='test2')
        make_friends(c, user1, user2)

        event_id = create_event(c, user1, 'test event 1', privacy='private')

        assert 1 == Event.select().count()
        assert 0 == Event.select().group(user1.group).count()
        assert 1 == Event.select().user(user1).count()
        assert 0 == Event.select().user(user2).count()

        event = Event.find(event_id)

        resp = api_post(c, user1, '/api/events/{}/invites'.format(event_id),
                        {'invited_id': user2.id})

        assert resp.status_code == 200, 'oops {}'.format(resp.data)
        assert 1 == Event.select().user(user2).count()
        count, page, results = EventAttendee.select().event(event).user(
            user2).execute()
        assert count == 1
        assert results[0] == user1
Ejemplo n.º 4
0
def test_create_event():
    from server.models.event import Event
    from server.models.user import User

    with client() as c:
        user1 = User.find(key='test')
        user2 = User.find(key='test2')

        create_event(c, user1, 'test event')

        resp = api_get(c, user1, '/api/events/')
        assert resp.status_code == 200, 'oops {}'.format(resp.data)
        data = ujson.loads(resp.data)
        assert data['objects'][0]['name'] == 'test event'
        assert data['objects'][0]['group'] == {'$ref': 'Group:1'}

        event_id = data['objects'][0]['id']
        event = Event.find(event_id)
        assert user1.is_attending(event), 'user is attending the new event'
        assert 1 == Event.select().count()

        event_id = create_event(c, user1, 'test event 2')
        user1 = User.find(key='test')
        assert user1.get_attending_id() == event_id
        assert 2 == Event.select().count(), '2 events total now'
        count, page, results = Event.select().group(user1.group).execute()
        assert 1 == count, 'only 1 in the group though, since the other has no attendees now'
        assert results[0].name == 'test event 2'
Ejemplo n.º 5
0
def notify_on_friend_attending(event_id, user_id, friend_id):
    num_attending = get_num_attending(event_id, user_id)
    if num_attending < 5:
        return

    try:
        event = Event.find(event_id)
        user = User.find(user_id)
    except DoesNotExist:
        return

    if event.is_expired:
        return

    rl_key = 'notify:nofa:{}:{}'.format(event_id, user_id)
    with rate_limit(rl_key, event.expires) as limited:
        if not limited:
            friends = list(islice(EventAttendee.select().event(event).user(user).limit(6), 5))
            if user in friends:
                friends.remove(user)
                num_attending -= 1

            logger.info('notifying user {} of {} friends attending event {}'.format(user_id, num_attending, event_id))
            if len(friends) >= 2:
                notification = Notification({
                    'user_id': user.id,
                    'type': 'system',
                    'navigate': '/users/me/events/{}'.format(event_id),
                    'badge': 1,
                    'message': '{}, {}, and {} others are going to {}'.format(
                        friends[0].full_name.encode('utf-8'), friends[1].full_name.encode('utf-8'),
                        num_attending - 2, event.name.encode('utf-8'))
                }).save()

                send_notification_push.delay(notification.to_primitive())
Ejemplo n.º 6
0
 def event(self):
     if self.event_id:
         from server.models.event import Event
         try:
             return Event.find(self.event_id)
         except DoesNotExist:
             logger.warn('event {} not found'.format(self.event_id))
     return None
Ejemplo n.º 7
0
    def get(self, event_id, message_id, headers):
        from server.models.user import User

        event = Event.find(event_id)
        if not g.user.can_see_event(event):
            abort(403, message='Can not see event')
        message = EventMessage.find(message_id)
        count, page, votes = self.select().eventmessage(message).execute()
        return self.serialize_list(User, votes, count, page), 200, headers
Ejemplo n.º 8
0
 def get(self, user_id, event_id, headers):
     event = Event.find(event_id)
     if not g.user.can_see_event(event):
         abort(403, message='Can not see event')
     query = self.select().event(event).user(g.user).secure(g.user)
     # if event.is_expired:
     #     query = query.by_votes()
     count, page, messages = query.execute()
     return self.serialize_list(self.model, messages, count, page), 200, headers
Ejemplo n.º 9
0
def tell_friend_user_not_attending(user_id, event_id, friend_id):
    try:
        user = User.find(user_id)
        event = Event.find(event_id)
        friend = User.find(friend_id)
    except DoesNotExist:
        return

    if not user.is_attending(event):
        event.remove_from_user_attending(friend, user)
Ejemplo n.º 10
0
def tell_friends_user_not_attending(user_id, event_id):
    try:
        user = User.find(user_id)
        event = Event.find(event_id)
    except DoesNotExist:
        return

    if not user.is_attending(event):
        for friend_id, score in wigo_db.sorted_set_iter(skey(user, 'friends')):
            tell_friend_user_not_attending.delay(user_id, event_id, friend_id)
Ejemplo n.º 11
0
def tell_friends_user_attending(user_id, event_id, notify=True):
    try:
        user = User.find(user_id)
        event = Event.find(event_id)
    except DoesNotExist:
        return

    if user.is_attending(event):
        for friend in user.friends_iter():
            if friend.can_see_event(event):
                tell_friend_user_attending.delay(user_id, event_id, friend.id,
                                                 notify)
Ejemplo n.º 12
0
def tell_friend_user_attending(user_id, event_id, friend_id, notify=True):
    try:
        user = User.find(user_id)
        event = Event.find(event_id)
        friend = User.find(friend_id)
    except DoesNotExist:
        return

    if user.is_attending(event):
        event.add_to_user_attending(friend, user)
        if notify:
            friend_attending.send(None, event=event, user=friend, friend=user)
Ejemplo n.º 13
0
def user_invited(event_id, inviter_id, invited_id):
    try:
        event = Event.find(event_id)
        inviter = User.find(inviter_id)
        invited = User.find(invited_id)
    except DoesNotExist:
        return

    # make sure i am seeing all my friends attending now
    for friend in invited.friends_iter():
        if friend.is_attending(event):
            event.add_to_user_attending(invited, friend)
Ejemplo n.º 14
0
def test_event_messages():
    from server.models.event import Event
    from server.models.user import User

    with client() as c:
        user1 = User.find(key='test')
        user2 = User.find(key='test2')
        event_id = create_event(c, user1, 'e1')
        event = Event.find(event_id)

        create_event_message(c, user1, event, 'test.jpg')
        assert 1 == EventMessage.select().event(event).count()
        assert 1 == EventMessage.select().event(event).user(user1).count()
        assert 0 == EventMessage.select().event(event).user(user2).count()

        make_friends(c, user1, user2)

        assert 1 == EventMessage.select().event(event).user(user2).count()
Ejemplo n.º 15
0
def test_event_message_votes():
    from server.models.event import Event
    from server.models.user import User
    from server.db import wigo_db

    with client() as c:
        user1 = User.find(key='test')
        user2 = User.find(key='test2')
        user3 = User.find(key='test3')

        make_friends(c, user2, user3)

        event_id = create_event(c, user1, 'e1')
        event = Event.find(event_id)

        message_id_1 = create_event_message(c, user1, event, 'test.jpg')
        message_id_2 = create_event_message(c, user1, event, 'test.jpg')

        message_1 = EventMessage.find(message_id_1)
        message_2 = EventMessage.find(message_id_2)

        resp = create_event_message_vote(c, user1, event, message_1)
        resp = create_event_message_vote(c, user2, event, message_2)
        resp = create_event_message_vote(c, user3, event, message_2)

        assert wigo_db.get_sorted_set_size(skey(message_1, 'votes')) == 1
        assert wigo_db.get_sorted_set_size(skey(message_2, 'votes')) == 2

        assert EventMessage.select().event(event).by_votes().get() == message_2

        resp = api_get(c, user1,
                       '/api/events/{}/messages/meta'.format(event_id))
        data = ujson.loads(resp.data)
        assert 1 == data[str(message_id_1)]['num_votes']

        make_friends(c, user1, user2)

        make_friends(c, user1, user3)

        resp = create_event_message_vote(c, user2, event, message_1)
        resp = create_event_message_vote(c, user3, event, message_1)

        assert EventMessage.select().event(event).by_votes().get() == message_1
Ejemplo n.º 16
0
    def get(self, event_id):
        event = Event.find(event_id)

        page = self.get_page()
        limit = self.get_limit()
        start = (page - 1) * limit

        num_friends = wigo_db.get_sorted_set_size(skey(g.user, 'friends'))

        # find the users top 5 friends. this is users with > 3 interactions
        top_5 = wigo_db.sorted_set_rrange_by_score(skey(
            g.user, 'friends', 'top'),
                                                   'inf',
                                                   3,
                                                   limit=5)
        if not top_5:
            top_5 = wigo_db.sorted_set_rrange_by_score(skey(g.user, 'friends'),
                                                       'inf',
                                                       3,
                                                       limit=5)

        friend_ids = wigo_db.sorted_set_range(skey(g.user, 'friends', 'alpha'),
                                              start, start + (limit - 1))
        for top_friend_id in top_5:
            if top_friend_id in friend_ids:
                friend_ids.remove(top_friend_id)

        if page == 1 and top_5:
            friend_ids = top_5 + friend_ids

        users = User.find(friend_ids)

        p = wigo_db.redis.pipeline()
        for user in users:
            p.zscore(skey(event, g.user, 'invited'), user.id if user else -1)

        scores = p.execute()
        for index, user in enumerate(users):
            if user:
                user.invited = scores[index] is not None

        return self.serialize_list(self.model, users, num_friends, page)
Ejemplo n.º 17
0
def notify_on_invite(inviter_id, invited_id, event_id):
    rl_key = 'notify:invite:{}:{}:{}'.format(inviter_id, invited_id, event_id)
    with rate_limit(rl_key, timedelta(hours=2)) as limited:
        if not limited:
            inviter = User.find(inviter_id)
            invited = User.find(invited_id)
            event = Event.find(event_id) if event_id else None

            message_text = '{} invited you out to {}'.format(inviter.full_name.encode('utf-8'),
                                                             event.name.encode('utf-8'))

            notification = Notification({
                'user_id': invited_id,
                'type': 'invite',
                'from_user_id': inviter_id,
                'navigate': '/users/me/events/{}'.format(event_id),
                'badge': 1,
                'message': message_text
            }).save()

            send_notification_push.delay(notification.to_primitive())
Ejemplo n.º 18
0
def test_attending():
    from server.models.event import Event, EventAttendee
    from server.models.user import User

    with client() as c:
        user1 = User.find(key='test')
        user2 = User.find(key='test2')

        create_event(c, user1, 'test event 1')
        event = Event.find(name='test event 1', group=user1.group)

        resp = api_post(c, user2, '/api/events/{}/attendees'.format(event.id),
                        {})
        assert resp.status_code == 200, 'oops {}'.format(resp.data)

        assert 2 == EventAttendee.select().event(event).count()
        assert 1 == EventAttendee.select().event(event).user(user1).count()
        assert 1 == EventAttendee.select().event(event).user(user2).count()

        make_friends(c, user1, user2)

        assert 2 == EventAttendee.select().event(event).user(user1).count()
Ejemplo n.º 19
0
    def get(self, user_id, headers):
        user = g.user
        group = g.group

        query = self.select().user(user)
        query = query.min(epoch(group.get_day_end() - timedelta(days=8)))
        query = query.max(epoch(group.get_day_end() + timedelta(hours=4)))

        count, page, events = query.execute()

        attending_id = user.get_attending_id()
        if attending_id:
            try:
                attending = Event.find(attending_id)
                if attending in events:
                    events.remove(attending)
                if 'page' not in request.args:
                    events.insert(0, attending)
                    attending.current_user_attending = True
            except DoesNotExist:
                logger.warn('Event {} not found'.format(attending_id))

        return self.serialize_list(self.model, events, count, page), 200, headers
Ejemplo n.º 20
0
def send_friend_invites(user_id, event_id):
    try:
        user = User.find(user_id)
        event = Event.find(event_id)
    except DoesNotExist:
        return

    if event.is_expired or not user.is_attending(event):
        return

    groups = {}
    for friend in user.friends_iter():
        if wigo_db.sorted_set_is_member(
                skey('event', event_id, user, 'invited'), friend.id):
            continue

        if friend.group_id:
            friend_group = groups.get(friend.group_id)
            if friend_group is None:
                friend_group = Group.find(friend.group_id)
                groups[friend.group_id] = friend_group

            distance = Location.getLatLonDistance(
                (user.group.latitude, user.group.longitude),
                (friend_group.latitude, friend_group.longitude))

            if distance > 160:  # > 160km, 100 miles
                continue

        try:
            invite = Invite()
            invite.user_id = user.id
            invite.invited_id = friend.id
            invite.event_id = event_id
            invite.save()
        except ValidationException, e:
            logger.warn('error creating invite, {}'.format(e.message))
Ejemplo n.º 21
0
def event_related_change(group_id, event_id, is_global=False, deleted=False):
    from server.db import redis

    lock = redis.lock('locks:group_event_change:{}:{}'.format(
        group_id, event_id),
                      timeout=120)
    if lock.acquire(blocking=False):
        try:
            agent.add_custom_parameter('group_id', group_id)
            logger.debug('recording event change in group {}'.format(group_id))

            if not deleted:
                try:
                    event = Event.find(event_id)
                    event.deleted = False
                except DoesNotExist:
                    event = Event({'id': event_id, 'group_id': group_id})
                    event.deleted = True
            else:
                event = Event({'id': event_id, 'group_id': group_id})
                event.deleted = True

            group = Group.find(group_id)

            with wigo_db.transaction(commit_on_select=False):
                # add to the time in case other changes come in while this lock is taken,
                # or in case the job queues get backed up
                group.track_meta('last_event_change',
                                 time() + EVENT_CHANGE_TIME_BUFFER)

                if is_global or event.is_global:
                    groups_to_add_to = get_all_groups()
                else:
                    radius = 100
                    population = group.population or 50000
                    if population < 60000:
                        radius = 40
                    elif population < 100000:
                        radius = 60

                    groups_to_add_to = get_close_groups(
                        group.latitude, group.longitude, radius)

                num_visited = 0
                for group_to_add_to in groups_to_add_to:
                    if group_to_add_to.id == group.id:
                        continue

                    # index this event into the close group
                    if event.deleted is False:
                        event.update_global_events(group=group_to_add_to)
                    else:
                        event.remove_index(group=group_to_add_to)

                    # track the change for the group
                    group_to_add_to.track_meta(
                        'last_event_change',
                        time() + EVENT_CHANGE_TIME_BUFFER)

                    num_visited += 1

                    if (num_visited % 25) == 0:
                        lock.extend(30)

        finally:
            lock.release()
Ejemplo n.º 22
0
 def get(self, user_id, event_id, headers):
     event = Event.find(event_id)
     if not g.user.can_see_event(event):
         abort(403, message='Can not see event')
     count, page, instances = self.select().user(g.user).event(event).execute()
     return self.serialize_list(self.model, instances, count, page), 200, headers