class EventMessageResource(WigoResource): model = EventMessage @user_token_required @api.response(200, 'Success', model=EventMessage.to_doc_list_model(api)) def get(self, event_id, message_id): message = self.model.find(self.get_id(message_id)) event = message.event if not g.user.can_see_event(event): abort(403, message='Can not see event') return self.serialize_list(self.model, [message]) @user_token_required @api.expect(EventMessage.to_doc_list_model(api)) @api.response(200, 'Success', model=EventMessage.to_doc_list_model(api)) def post(self, event_id, message_id): message = self.edit(message_id, request.get_json()) return self.serialize_list(self.model, [message]) @user_token_required def delete(self, event_id, message_id): message = self.model.find(self.get_id(message_id)) self.check_edit(message) message.delete() return {'success': True}
def tell_friend_delete_event_message(user_id, event_id, message_id, friend_id): try: friend = User.find(friend_id) except DoesNotExist: return message = EventMessage({ 'id': message_id, 'user_id': user_id, 'event_id': event_id }) message.remove_for_user(friend)
def notify_on_eventmessage_vote(voter_id, message_id): try: voter = User.find(voter_id) message = EventMessage.find(message_id) except DoesNotExist: return user = message.user type = 'video' if message.media_mime_type == 'video/mp4' else 'photo' # don't send to self or if not friend if (voter_id == message.user_id) or (not user.is_friend(voter_id)): return with rate_limit('notify:vote:%s:%s:%s' % (message.user_id, message_id, voter_id), timedelta(hours=2)) as limited: if not limited: message_text = '{name} liked your {type} in {event}'.format( name=voter.full_name.encode('utf-8'), type=type, event=message.event.name.encode('utf-8')) notification = Notification({ 'user_id': message.user_id, 'type': 'eventmessage.vote', 'from_user_id': voter_id, 'navigate': '/users/me/events/{}/messages/{}'.format(message.event_id, message.id), 'message': message_text }).save() send_notification_push.delay(notification.to_primitive())
def on_thumbnail_upload(key): if key != Configuration.API_HOOK_KEY: abort(400, message='Invalid api key') data = request.data or request.form.get('results') or '' try: data = ujson.loads(data) except ValueError: logger.error('error parsing blitline callback data, {data}'.format(data=data)) abort(400, message='Bad json data') images = data.get('images') errors = data.get('errors') if images: for image in images: type_and_id = ujson.loads(image.get('image_identifier')) s3_path = urlparse(image.get('s3_url')).path.replace('/wigo-uploads/', '') if type_and_id['type'] == 'EventMessage': message = EventMessage.find(type_and_id['id']) if type_and_id.get('thumbnail') is not False: message.thumbnail = s3_path else: message.media = s3_path message.save() return jsonify(success=True) else: failed_ids = data.get('failed_image_identifiers') logger.error('error creating thumbnail for {ids}, {error}'.format(ids=failed_ids, error=errors)) return jsonify(success=False)
def tell_friend_event_message(message_id, friend_id): try: message = EventMessage.find(message_id) friend = User.find(friend_id) except DoesNotExist: return message.record_for_user(friend)
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 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()
def tell_friends_event_message(message_id): try: message = EventMessage.find(message_id) user_id = message.user_id except: return for friend_id, score in wigo_db.sorted_set_iter( skey('user', user_id, 'friends')): tell_friend_event_message.delay(message_id, friend_id)
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 post(self, event_id, message_id): try: message = EventMessage.find(message_id) EventMessageVote({ 'message_id': message_id, 'user_id': g.user.id }).save() return {'success': True} except DoesNotExist: abort(400, message='Event message missing, probably deleted')
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 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 annotate_events(self, events): alimit = int(request.args.get('attendees_limit', 5)) mlimit = int(request.args.get('messages_limit', 5)) current_user = g.user user_context = current_user if '/users/' in request.path else None # fill in attending on each event query = EventAttendee.select().events(events).user(user_context).secure(g.user) count, page, attendees_by_event = query.limit(alimit).execute() if count: for event, attendees in zip(events, attendees_by_event): # make sure the event the current user is attending is in front if hasattr(event, 'current_user_attending'): count, attendees = attendees if attendees and attendees[0] != g.user: if g.user in attendees: attendees.remove(g.user) attendees.insert(0, g.user) attendees = (count, attendees) event.attendees = attendees event.num_attending = attendees[0] def capture_messages(events, query): count, page, messages_by_event = query.limit(mlimit).execute() if count: for event, messages in zip(events, messages_by_event): event.messages = messages base_query = EventMessage.select().user(user_context).secure(g.user) capture_messages(events, base_query.events(events)) # expired, current = partition(events, lambda e: e.is_expired) # base_query = EventMessage.select().user(user_context).secure(g.user) # capture_messages(current, base_query.events(current)) # capture_messages(expired, base_query.events(expired).by_votes()) filtered = [] for event in events: include_event = True if not hasattr(event, 'attendees') or len(event.attendees[1]) == 0: include_event = False if event.is_expired: if not hasattr(event, 'messages') or len(event.messages[1]) == 0: include_event = False if include_event: filtered.append(event) return filtered
class UserEventMessageListResource(WigoResource): model = EventMessage @user_token_required @check_last_modified('user', 'last_event_change') @api.response(200, 'Success', model=EventMessage.to_doc_list_model(api)) 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
class EventMessageListResource(WigoResource): model = EventMessage @user_token_required @check_last_modified('group', 'last_event_change') @api.response(200, 'Success', model=EventMessage.to_doc_list_model(api)) def get(self, 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).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 @user_token_required @api.expect(EventMessage.to_doc_list_model(api)) @api.response(200, 'Success', model=Event.to_doc_list_model(api)) def post(self, event_id): data = dict(request.get_json()) data['event_id'] = event_id message = self.create(data) return self.serialize_list(self.model, [message])
class UserEventMessagesMetaListResource(WigoResource): model = EventMessage @user_token_required @check_last_modified('user', 'last_event_change') @api.response(200, 'Success', model=EventMessage.to_doc_list_model(api)) def get(self, user_id, event_id, headers): message_meta = {} message_ids = wigo_db.sorted_set_range(user_eventmessages_key(g.user, event_id)) for message_id in message_ids: message_meta[message_id] = { 'num_votes': wigo_db.get_sorted_set_size(user_votes_key(g.user, message_id)), 'voted': wigo_db.sorted_set_is_member(user_votes_key(g.user, message_id), g.user.id) } return message_meta, 200, headers
def notify_on_eventmessage(message_id): try: message = EventMessage.find(message_id) except DoesNotExist: return user = message.user if message.event.is_expired: return type = 'video' if message.media_mime_type == 'video/mp4' else 'photo' for friend in EventAttendee.select().user(message.user).event(message.event): if friend == user: continue with rate_limit('notify:eventmessage:{}:{}:{}'.format(user.id, message.event.id, friend.id), timedelta(hours=2)) as limited: if limited: return message_text = '{name} posted a {type} in {event}'.format( name=user.full_name.encode('utf-8'), type=type, event=message.event.name.encode('utf-8')) notification = Notification({ 'user_id': friend.id, 'type': 'eventmessage.post', 'from_user_id': message.user_id, 'navigate': '/users/me/events/{}/messages/{}'.format(message.event_id, message.id), 'message': message_text }).save() send_notification_push.delay(notification.to_primitive())
def process_eventmessage_image(message_id): if not Configuration.BLITLINE_APPLICATION_ID: logger.warning('blitline not configured, ignoring thumbnail request') return try: message = EventMessage.find(message_id) except DoesNotExist: return if message.media_mime_type == 'video/mp4': media = message.image if media is None and message.thumbnail: media = message.thumbnail message.image = media message.thumbnail = None message.save() else: media = message.media if not media: return path = os.path.split(urlparse(media).path)[0] function = { 'name': 'resize_to_fit', 'params': { 'width': 150 }, 'save': { 'image_identifier': ujson.dumps({ 'type': 'EventMessage', 'id': message.id, 'thumbnail': True }), 's3_destination': { 'bucket': 'wigo-uploads', 'key': path + '/' + str(message.id) + '-thumb.jpg', 'headers': { 'Content-Type': 'image/jpeg', 'Cache-Control': 'max-age=86400' } } } } # the hook is defined in uploads.py job_data = { 'application_id': Configuration.BLITLINE_APPLICATION_ID, 'src': 'https://' + Configuration.UPLOADS_CDN + '/' + media, 'postback_url': 'https://' + Configuration.API_HOST + '/api/hooks/blitline/' + Configuration.API_HOOK_KEY + '/', 'functions': [function] } resp = requests.post('http://api.blitline.com/job', data={'json': ujson.dumps(job_data)}, timeout=10) if resp.status_code == 200: json = resp.json() if 'error' in json: error_str = 'error creating blitline thumbnail job for ' \ 'event message {id}, {error}'.format(id=message.id, error=json.get('error')) logger.error(error_str) raise Exception(error_str) else: error_str = 'error creating blitline thumbnail job ' \ 'for event message {id}, {error}'.format(id=message.id, error=resp.content) logger.error(error_str) raise Exception(error_str)
def delete_user(user_id, group_id): logger.info('deleting user {}'.format(user_id)) friend_ids = wigo_db.sorted_set_range(skey('user', user_id, 'friends')) with wigo_db.transaction(commit_on_select=False): # remove from attendees for event_id, score in wigo_db.sorted_set_iter( skey('user', user_id, 'events')): wigo_db.sorted_set_remove(skey('event', event_id, 'attendees'), user_id) for friend_id in friend_ids: wigo_db.sorted_set_remove( skey('user', friend_id, 'event', event_id, 'attendees'), user_id) # remove event message votes for message_id, score in wigo_db.sorted_set_iter( skey('user', user_id, 'votes')): wigo_db.sorted_set_remove( skey('eventmessage', message_id, 'votes'), user_id) for friend_id in friend_ids: wigo_db.sorted_set_remove( user_votes_key(friend_id, message_id), user_id) # remove event messages for message_id, score in wigo_db.sorted_set_iter( skey('user', user_id, 'event_messages')): message = EventMessage.find(message_id) event_id = message.event_id wigo_db.sorted_set_remove(skey('event', event_id, 'messages'), message_id) wigo_db.sorted_set_remove( skey('event', event_id, 'messages', 'by_votes'), message_id) for friend_id in friend_ids: wigo_db.sorted_set_remove( skey('user', friend_id, 'event', event_id, 'messages'), message_id) wigo_db.sorted_set_remove( skey('user', friend_id, 'event', event_id, 'messages', 'by_votes'), message_id) for friend_id in friend_ids: # remove conversations wigo_db.sorted_set_remove(skey('user', friend_id, 'conversations'), user_id) wigo_db.delete(skey('user', friend_id, 'conversation', user_id)) wigo_db.delete(skey('user', user_id, 'conversation', friend_id)) # remove friends wigo_db.sorted_set_remove(skey('user', friend_id, 'friends'), user_id) wigo_db.sorted_set_remove( skey('user', friend_id, 'friends', 'top'), user_id) wigo_db.sorted_set_remove( skey('user', friend_id, 'friends', 'alpha'), user_id) wigo_db.set_remove(skey('user', friend_id, 'friends', 'private'), user_id) # remove friend requests for friend_id in wigo_db.sorted_set_range( skey('user', user_id, 'friend_requested')): wigo_db.sorted_set_remove( skey('user', friend_id, 'friend_requests'), user_id) wigo_db.sorted_set_remove( skey('user', friend_id, 'friend_requests', 'common'), user_id) # remove messages for message_id, score in wigo_db.sorted_set_iter( skey('user', user_id, 'messages')): wigo_db.delete(skey('message', message_id)) wigo_db.delete(skey('user', user_id, 'events')) wigo_db.delete(skey('user', user_id, 'friends')) wigo_db.delete(skey('user', user_id, 'friends', 'top')) wigo_db.delete(skey('user', user_id, 'friends', 'private')) wigo_db.delete(skey('user', user_id, 'friends', 'alpha')) wigo_db.delete(skey('user', user_id, 'friends', 'friend_requested')) wigo_db.delete(skey('user', user_id, 'friends', 'friend_requests')) wigo_db.delete( skey('user', user_id, 'friends', 'friend_requests', 'common')) wigo_db.delete(skey('user', user_id, 'blocked')) wigo_db.delete(skey('user', user_id, 'notifications')) wigo_db.delete(skey('user', user_id, 'notifs'), replicate=False) wigo_db.delete(skey('user', user_id, 'conversations')) wigo_db.delete(skey('user', user_id, 'tapped')) wigo_db.delete(skey('user', user_id, 'votes')) wigo_db.delete(skey('user', user_id, 'messages'))