예제 #1
0
 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.')
예제 #2
0
 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.')
예제 #3
0
 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.')
예제 #4
0
 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)
예제 #5
0
 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.')
예제 #6
0
 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.')
예제 #7
0
 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.'
     )
예제 #8
0
 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.')
예제 #9
0
 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)
예제 #10
0
 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.'
     )
예제 #11
0
 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)
예제 #12
0
    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)