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'
def post(self): json = request.get_json() if 'city_id' in json: group = get_group_by_city_id(json['city_id']) elif 'group_id' in json: group = Group.find(json['group_id']) else: group = g.group try: event = Event({ 'name': json.get('name'), 'group_id': group.id, 'owner_id': g.user.id, 'privacy': json.get('privacy') or 'public' }) if 'date' in json: date = parse(json.get('date')) event.date = group.get_day_start(date) event.expires = group.get_day_end(date) else: event.date = group.get_day_start() event.expires = group.get_day_end() if 'latitude' in json: event.latitude = json.get('latitude') if 'longitude' in json: event.longitude = json.get('longitude') event.save() return self.serialize_list(Event, [event]) except AlreadyExistsException, e: return self.handle_already_exists_exception(e)
class UserEventListResource(WigoResource): model = Event def get_limit(self, default=5): return super(UserEventListResource, self).get_limit(default) @user_token_required @check_last_modified('user', 'last_event_change') @api.response(200, 'Success', model=Event.to_doc_list_model(api)) 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
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())
def post(self, application_id): args = self.reqparse.parse_args() args['application_id'] = application_id event = Event(args) db.session.add(event) db.session.commit() return 'Event added!', 201
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
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())
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
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
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
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)
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)
def delete_history(u, f): with wigo_db.transaction(commit_on_select=False): for message in EventMessage.select().key(skey(u, 'event_messages')): if message.user and message.event: message.remove_for_user(f) for event in Event.select().user(u): if wigo_db.sorted_set_is_member(user_attendees_key(f, event), u.id): event.remove_from_user_attending(f, u)
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)
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)
def capture_history(u, f): # capture each of the users posted photos with wigo_db.transaction(commit_on_select=False): for message in EventMessage.select().key(skey( u, 'event_messages')).min(min): if message.user and message.event: message.record_for_user(f) # capture the events being attended for event in Event.select().user(u).min(min): if u.is_attending(event) and f.can_see_event(event): event.add_to_user_attending(f, u)
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)
def test_user_events(): 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 1') create_event(c, user2, 'test event 2') assert 2 == Event.select().count(), '2 events total now' assert 2 == Event.select().group(user1.group).count() count, page, results = Event.select().user(user1).execute() assert 1 == count assert results[0].name == 'test event 1' count, page, results = Event.select().user(user2).execute() assert 1 == count assert results[0].name == 'test event 2'
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
class EventResource(WigoDbResource): model = Event @user_token_required @api.response(200, 'Success', model=Event.to_doc_list_model(api)) def get(self, model_id): return super(EventResource, self).get(model_id) def check_get(self, event): super(EventResource, self).check_get(event) if not g.user.can_see_event(event): abort(403, message='Can not see event event') @user_token_required @api.expect(Event.to_doc_list_model(api)) @api.response(200, 'Success', model=Event.to_doc_list_model(api)) def post(self, model_id): return super(EventResource, self).post(model_id) @api.response(501, 'Not implemented') def delete(self, model_id): abort(501, message='Not implemented')
def new_group(group_id): group = Group.find(group_id) logger.info('new group {} created, importing events'.format( group.name.encode('utf-8'))) num_imported = 0 imported = set() min = epoch(group.get_day_end() - timedelta(days=7)) with wigo_db.transaction(commit_on_select=False): for close_group in get_close_groups(group.latitude, group.longitude, 100): if close_group.id == group.id: continue for event in Event.select().group(close_group).min(min): # only import the events the group actually owns if event.group_id != close_group.id: continue # no double imports if event.id not in imported: event.update_global_events(group=group) imported.add(event.id) num_imported += 1 for event in Event.select().key(skey('global', 'events')).min(min): if event.id not in imported: event.update_global_events(group=group) imported.add(event.id) num_imported += 1 logger.info('imported {} events into group {}'.format( num_imported, group.name.encode('utf-8'))) group.track_meta('last_event_change', expire=None) group.status = 'active' group.save()
class FutureUserEventListResource(WigoResource): model = Event @user_token_required @check_last_modified('user', 'last_event_change') @api.response(200, 'Success', model=Event.to_doc_list_model(api)) def get(self, user_id, headers): user = g.user group = g.group query = self.select().user(user).order('asc') query = query.min(epoch(group.get_day_start())) query = query.max(epoch(group.get_day_end() + timedelta(days=10))) count, page, instances = query.execute() return self.serialize_list(self.model, instances, count, page), 200, headers
class FutureEventListResource(WigoDbListResource): model = Event def get_limit(self, default=10): return super(FutureEventListResource, self).get_limit(default) @user_token_required @check_last_modified('group', 'last_event_change') @api.response(200, 'Success', model=Event.to_doc_list_model(api)) def get(self, headers): user = g.user group = g.group query = self.select().group(group).order('asc') query = query.min(epoch(group.get_day_start())) query = query.max(epoch(group.get_day_end() + timedelta(days=10))) count, page, events = query.execute() return self.serialize_list(self.model, events, count, page), 200, headers
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()
class FutureEventMetaListResource(WigoResource): @user_token_required @check_last_modified('group', 'last_event_change') @api.response(200, 'Success', model=Event.to_doc_list_model(api)) def get(self, headers): group = g.group meta = {} dates = [(group.get_day_end() + timedelta(days=i)) for i in range(10)] p = wigo_db.redis.pipeline() for d in dates: p.zcount(skey(group, 'events'), epoch(d), epoch(d + timedelta(hours=3))) counts = p.execute() for index, d in enumerate(dates): meta[(d - timedelta(days=1)).date().isoformat()] = counts[index] return meta, 200, headers
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
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)
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())
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()
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