def get_user_posts(username, skip=0, limit=10): user = UserModel.get_user(username) if user: posts = [PostModel.get_post(post_id) for post_id in user['posts']] posts.sort(key=lambda post: post['timestamp'], reverse=True) return posts[skip:skip + limit] raise WriteError(f'Error in querying posts. User may not exist.')
def add_user_post(username, post_id, title, audio_link, timestamp, description=None, image_link=None): user = UserModel.get_user(username) if user: DB.posts.insert({ '_id': post_id, 'username': username, 'title': title, 'description': description, 'audio_link': audio_link, 'image_link': image_link, 'timestamp': timestamp, 'comments': [], 'liked_by': [], 'view_count': 0 }) DB.users.find_one_and_update({'_id': username}, {'$addToSet': { 'posts': post_id }}) return PostModel.get_post(post_id) raise WriteError('Error in creating post. User may not exist.')
def get_user_discover_posts(username, skip=0, limit=10, seed=0): user = UserModel.get_user(username) if user: all_posts = list(DB.posts.find({'username': {'$ne': username}})) permuted_posts = PostModel.permute_with_discovery_algorithm( all_posts, seed) return permuted_posts[skip:skip + limit] raise WriteError(f'Error in querying posts. User may not exist.')
def login_user(username_or_email, password): try: user_token = AuthUtil.get_user_token( username_or_email=username_or_email, password=password) username = AuthUtil.decode_user_token(user_token) user_auth_data = AuthUtil.get_user(username) if user_auth_data['email_verified']: user_app_data = UserModel.get_user(username, show_following_pics=True, show_follower_pics=True) data = { 'username': user_auth_data['username'], 'email': user_auth_data['email'], 'email_verified': user_auth_data['email_verified'], 'followers': user_app_data['followers'], 'followings': user_app_data['followings'], 'posts': user_app_data['posts'], 'number_of_followers': len(user_app_data['followers']), 'number_of_following': len(user_app_data['followings']), 'number_of_posts': len(user_app_data['posts']), 'description': user_app_data['description'], 'notifications': user_app_data['notifications'], 'picture': user_app_data['picture'], 'user_token': user_token } return make_response( jsonify({ 'status': 'success', 'message': 'User successfully login.', 'data': data }), 200) else: return make_response( jsonify({ 'status': 'fail', 'message': 'User email not verified. Please verify email to login.', }), 400) except Auth0Error as e: return make_response( jsonify({ 'status': 'fail', 'message': f'Auth0 Error: {str(e)}', }), 400) except OperationFailure as e: return make_response( jsonify({ 'status': 'fail', 'message': f'DB Operation Error: {str(e)}', }), 400) except ConnectionFailure as e: return make_response( jsonify({ 'status': 'fail', 'message': f'DB Connection Error: {str(e)}', }), 500)
def like_post(post_id, username): user = UserModel.get_user(username) post = PostModel.get_post(post_id) if user and post: DB.posts.find_one_and_update({'_id': post_id}, {'$addToSet': { 'liked_by': username }}) return PostModel.get_post(post_id) raise WriteError(f'Error in liking post. User or post may not exist.')
def get_user_feed_posts(username, skip=0, limit=10): user = UserModel.get_user(username) if user: followings = [username for username in user['followings']] posts = [] for username in followings: posts.extend(PostModel.get_user_posts(username)) posts.sort(key=lambda post: post['timestamp'], reverse=True) return posts[skip:skip + limit] raise WriteError(f'Error in querying posts. User may not exist.')
def remove_user_post(username, post_id): user = UserModel.get_user(username) post = PostModel.get_post(post_id) if post['_id'] in user['posts']: post_resp = DB.posts.find_one_and_delete({'_id': post_id}) user_resp = DB.users.find_one_and_update( {'_id': username}, {'$pull': { 'posts': post_id }}) return user_resp, post_resp raise WriteError( f'Error in removing post. User may not be authorized to remove this post.' )
def add_comment(post_id, username, text, timestamp): post = PostModel.get_post(post_id) user = UserModel.get_user(username) if user and post: comment = { 'username': username, 'text': text, 'timestamp': timestamp } DB.posts.find_one_and_update({'_id': post_id}, {'$push': { 'comments': comment }}) return PostModel.get_post(post_id) raise WriteError( f'Error in adding comment. User or post may not exist.')
def get_user(username, auth_info=True): try: user_data = UserModel.get_user(username, show_following_pics=True, show_follower_pics=True) data = {'username': username} data.update({ 'followers': user_data['followers'], 'followings': user_data['followings'], 'posts': user_data['posts'], 'number_of_followers': len(user_data['followers']), 'number_of_following': len(user_data['followings']), 'number_of_posts': len(user_data['posts']), 'description': user_data['description'], 'picture': user_data['picture'], }) if auth_info: data.update({ 'email': user_data['email'], 'notifications': user_data['notifications'] }) return make_response( jsonify({ 'status': 'success', 'message': 'User successfully retrieved.', 'data': data }), 200) except Auth0Error as e: return make_response( jsonify({ 'status': 'fail', 'message': f'Auth0 Error: {str(e)}', }), 400) except OperationFailure as e: return make_response( jsonify({ 'status': 'fail', 'message': f'DB Operation Error: {str(e)}', }), 400) except ConnectionFailure as e: return make_response( jsonify({ 'status': 'fail', 'message': f'DB Connection Error: {str(e)}', }), 500)
def update_user_post(username, post_id, **updates): user = UserModel.get_user(username) post = PostModel.get_post(post_id) if post['_id'] in user['posts']: updated_document = {'_id': post_id} if 'title' in updates: updated_document['title'] = updates['title'] if 'description' in updates: updated_document['description'] = updates['description'] if 'audio_link' in updates: updated_document['audio_link'] = updates['audio_link'] if 'image_link' in updates: updated_document['image_link'] = updates['image_link'] DB.posts.find_one_and_update({'_id': post_id}, {'$set': updated_document}) return PostModel.get_post(post_id) raise WriteError( f'Error in removing post. User may not be authorized to remove this post.' )
def get_post(post_id): try: post_data = PostModel.get_post(post_id) profile_picture = UserModel.get_user( post_data["username"])['picture'] post_data["profile_picture"] = profile_picture return make_response( jsonify({ 'status': 'success', 'message': 'Posts successfully queried.', 'data': post_data }), 200) except OperationFailure as e: return make_response( jsonify({ 'status': 'fail', 'message': f'DB Operation Error: {str(e)}', }), 400) except ConnectionFailure as e: return make_response( jsonify({ 'status': 'fail', 'message': f'DB Connection Error: {str(e)}', }), 500)
def create_user_post(username, title, audio_file, description=None, image_file=None): try: post_id = uuid.uuid4().hex timestamp = datetime.utcnow().isoformat() file_name, file_ext = os.path.splitext(audio_file.filename) # todo: multithread or multiprocess the audio conversion cos it's blocking and uses high cpu audio = AudioSegment.from_file(audio_file, format=file_ext.lstrip('.')) if len(audio ) > 12 * 60 * 1000: # len(audio) is audio duration in ms return make_response( jsonify({ 'status': 'fail', 'message': f'Audio duration is longer than 12 minutes, actual duration = {len(audio)/1000/60}min.' }), 400) # export in memory, not stored to disk audio_buffer = io.BytesIO() # normalize audio amplitude (volume) to -20 dBFS (smaller is quieter) # src: https://github.com/jiaaro/pydub/issues/90#issuecomment-75551606 target_dBFS = -20 change_in_dBFS = target_dBFS - audio.dBFS normalized_audio = audio.apply_gain(change_in_dBFS) normalized_audio.export(audio_buffer, format='mp3') audio_link = upload(audio_buffer, uuid.uuid4().hex + '.mp3') audio_buffer.close() image_link = None if image_file is not None: file_name, file_ext = os.path.splitext(image_file.filename) image_buffer = io.BytesIO() process_image(image_file, image_buffer) image_link = upload(image_buffer, uuid.uuid4().hex + file_ext) image_buffer.close() post_data = PostModel.add_user_post(username=username, post_id=post_id, title=title, timestamp=timestamp, audio_link=audio_link, description=description, image_link=image_link) user_data = UserModel.get_user(username) for follower_username in user_data['followers']: UserModel.add_notification_message( follower_username, f'made a new post!', user_ref=username, post_ref=post_id, ) return make_response( jsonify({ 'status': 'success', 'message': 'Post successfully created.', 'data': post_data }), 201) except CouldntDecodeError as e: return make_response( jsonify({ 'status': 'fail', 'message': f'PyDub failed to decode: {str(e)}', }), 400) except CouldntEncodeError as e: return make_response( jsonify({ 'status': 'fail', 'message': f'PyDub failed to encode: {str(e)}', }), 500) except UnidentifiedImageError as e: return make_response( jsonify({ 'status': 'fail', 'message': f'PIL failed to read image: {str(e)}', }), 400) except OperationFailure as e: return make_response( jsonify({ 'status': 'fail', 'message': f'DB Operation Error: {str(e)}', }), 400) except ConnectionFailure as e: return make_response( jsonify({ 'status': 'fail', 'message': f'DB Connection Error: {str(e)}', }), 500) except ClientError as e: return make_response( jsonify({ 'status': 'fail', 'message': f'S3 Connection Error: {str(e)}', }), 500)