def accept_friend_request(self, from_user_email: str, to_user_email: str) -> NoReturn: """ Accepts an existing friend request :raises: UnexistentFriendRequest: the friend request does not exist or is not pending :param from_user_email: the user that requested the friendship :param to_user_email: the target user of the request """ if from_user_email not in self.get_friend_requests(to_user_email): raise UnexistentFriendRequest cursor = self.conn.cursor() PostgresUtils.safe_query_run( self.logger, self.conn, cursor, DELETE_FRIEND_REQUEST_QUERY.format( self.friend_requests_table_name), (from_user_email, to_user_email)) self.conn.commit() friend_tuple = list(sorted([from_user_email, to_user_email])) friend_tuple = (friend_tuple[0], friend_tuple[1]) cursor.execute(NEW_FRIENDS_QUERY.format(self.friends_table_name), friend_tuple) self.conn.commit() cursor.close()
def last_days_api_calls(self, days: int) -> Generator[List[ApiCall], None, None]: """ Gets a generator of the last days api calls :param days: the number of days back :return: a generator of lists of api calls """ cursor = self.conn.cursor() PostgresUtils.safe_query_run( self.logger, self.conn, cursor, COUNT_ROWS_API_CALLS_QUERY.format( app_server_api_calls_table=self.app_server_api_calls_table), (days, )) result = cursor.fetchone() pages = int(math.ceil(result[0] / DEFAULT_BATCH_SIZE)) for page in range(pages): PostgresUtils.safe_query_run( self.logger, self.conn, cursor, GET_PAGINATED_API_CALLS_QUERY.format( app_server_api_calls_table=self.app_server_api_calls_table ), (days, DEFAULT_BATCH_SIZE, page * DEFAULT_BATCH_SIZE)) result = cursor.fetchall() # path, status, datetime, "time", method yield [ ApiCall(path=r[0], status=r[1], timestamp=r[2], time=r[3], method=r[4]) for r in result ]
def get_conversation(self, requestor_email: str, other_user_email: str, per_page: int, page: int) -> Tuple[List[PrivateMessage], int]: """ Get the paginated conversation between user1 and user2 :raises: NoMoreMessagesError: the page has no messages :param requestor_email: the email of user1 :param other_user_email: the email of user2 :param per_page: the messages per page :param page: the page for the message, starting from 0 :return: the list of private messages and the number of pages """ self.logger.debug("Geting conversation between %s and %s" % (requestor_email, other_user_email)) cursor = self.conn.cursor() PostgresUtils.safe_query_run( self.logger, self.conn, cursor, COUNT_ROWS_CONVERSATION_QUERY.format( user_messages_table_name=self.user_messages_table_name, user_deleted_messages_table_name=self. user_deleted_messages_table_name), (requestor_email, other_user_email, requestor_email, other_user_email, requestor_email)) result = cursor.fetchone() pages = int(math.ceil(result[0] / per_page)) if not page < pages and page != 0: raise NoMoreMessagesError() PostgresUtils.safe_query_run( self.logger, self.conn, cursor, GET_PAGINATED_CONVERSATION_QUERY.format( user_messages_table_name=self.user_messages_table_name, user_deleted_messages_table_name=self. user_deleted_messages_table_name), (requestor_email, other_user_email, requestor_email, other_user_email, requestor_email, per_page, page * per_page)) result = cursor.fetchall() self.conn.commit() cursor.close() # from_user, to_user, message, datetime result = [ PrivateMessage(from_user=r[0], to_user=r[1], message=r[2], timestamp=r[3]) for r in result ] return result, pages
def register_api_call(self, api_call: ApiCall) -> NoReturn: """ Registers an api call :param api_call: the api call to register """ cursor = self.conn.cursor() PostgresUtils.safe_query_run( self.logger, self.conn, cursor, ADD_API_CALL_QUERY.format( app_server_api_calls_table=self.app_server_api_calls_table), (self.server_alias, api_call.path, api_call.status, api_call.timestamp.isoformat(), api_call.time, api_call.method)) self.conn.commit() cursor.close()
def get_friend_requests(self, user_email: str) -> List[str]: """ Gets all the user emails that have sent a user request to the user :param user_email: the user to query for its friend requests :return: a list of emails """ self.logger.debug("Getting friend requests for %s" % user_email) cursor = self.conn.cursor() PostgresUtils.safe_query_run( self.logger, self.conn, cursor, FRIEND_REQUEST_QUERY.format(self.friend_requests_table_name) % user_email) result = cursor.fetchall() cursor.close() return [r[0] for r in result]
def get_friends(self, user_email: str) -> List[str]: """ Gets all the user emails that are friends of the user :param user_email: the user to query for its friend :return: a list of emails """ self.logger.debug("Getting friends for %s" % user_email) cursor = self.conn.cursor() PostgresUtils.safe_query_run( self.logger, self.conn, cursor, ALL_FRIENDS_QUERY.format(self.friends_table_name) % (user_email, user_email)) result = cursor.fetchall() cursor.close() friend_emails = [t[0] for t in result] + [t[1] for t in result] return [f for f in friend_emails if f != user_email]
def delete_friendship(self, user_email1: str, user_email2: str) -> NoReturn: """ Delete friendship if exists :param user_email1: first user email :param user_email2: second user email """ friend_tuple = list(sorted([user_email1, user_email2])) friend_tuple = (friend_tuple[0], friend_tuple[1]) self.logger.debug("Deleting friendship between %s and %s" % (user_email1, user_email2)) cursor = self.conn.cursor() PostgresUtils.safe_query_run( self.logger, self.conn, cursor, DELETE_FRIEND_QUERY.format(self.friends_table_name), friend_tuple) cursor.close() self.conn.commit()
def notify(self, user_email: str, title: str, body: str, payload: Dict) -> NoReturn: """ Sends the payload a notification the the user if has registered an app token for that user :param user_email: the user email for sending the payload :param title: the title of the notification :param body: the body of the notification :param payload: the payload to send """ self.logger.debug("Sending notification to %s" % user_email) cursor = self.conn.cursor() try: PostgresUtils.safe_query_run( self.logger, self.conn, cursor, SEARCH_NOTIFICATION_TOKEN.format( notification_tokens_table_name=self. notification_tokens_table_name), (user_email, )) result = cursor.fetchone() except Exception: self.logger.exception("Couldn't send notification") cursor.close() return if result: token = result[0] cursor.close() else: cursor.close() return try: r = requests.post(EXPO_SEND_NOTIFICATION_ENDPOINT, json={ "to": token, "title": title, "body": body, "data": payload }, timeout=NOTIFICATION_SEND_TIMEOUT) r.raise_for_status() except Exception: self.logger.exception("Couldn't send notification") return
def set_notification_token(self, user_email: str, token: str) -> NoReturn: """ Sets the notification token for a user email :param user_email: the user email for setting the notification token :param token: the token to set """ self.logger.debug("Setting notification token for %s" % user_email) cursor = self.conn.cursor() try: PostgresUtils.safe_query_run( self.logger, self.conn, cursor, NOTIFICATION_TOKEN_SAVE.format( notification_tokens_table_name=self. notification_tokens_table_name), (token, user_email, token)) except Exception: self.logger.exception("Couldn't register notification token") self.conn.commit() cursor.close()
def are_friends(self, user_email1: str, user_email2: str) -> bool: """ Check if user1 is friend with user2 :param user_email1: the first user email :param user_email2: the second user email :return: a boolean indicating whether user1 is friend user2's friend """ self.logger.debug("Checking whether %s and %s are friends" % (user_email1, user_email2)) cursor = self.conn.cursor() friends_ordered = tuple(list(sorted([user_email1, user_email2]))) PostgresUtils.safe_query_run( self.logger, self.conn, cursor, CHECK_FRIENDS_QUERY.format(self.friends_table_name) % friends_ordered) result = cursor.fetchone() cursor.close() if not result: return False return True
def delete_conversation(self, deletor_email: str, deleted_email: str) -> NoReturn: """ Deletes the conversation between two users but just for the deletor :param deletor_email: the email of the one that deletes the conversation :param deleted_email: the email of the other user of the conversation """ self.logger.debug("%s deleting conversation with %s" % (deletor_email, deleted_email)) cursor = self.conn.cursor() PostgresUtils.safe_query_run( self.logger, self.conn, cursor, DELETE_CONVERSATION_QUERY.format( user_messages_table_name=self.user_messages_table_name, user_deleted_messages_table_name=self. user_deleted_messages_table_name), (deletor_email, deletor_email, deleted_email, deletor_email, deleted_email, deletor_email)) self.conn.commit() cursor.close()
def exists_friend_request(self, from_user_email: str, to_user_email: str) -> bool: """ Check if exists friend request from 'requestor' to 'receiver' :param from_user_email: the requestor of the friendship :param to_user_email: the receiver of the request :return: a boolean indicating whether the friend request exists """ self.logger.debug("Checking whether %s sent a friend request to %s" % (from_user_email, to_user_email)) cursor = self.conn.cursor() PostgresUtils.safe_query_run( self.logger, self.conn, cursor, CHECK_FRIEND_REQUEST_QUERY.format(self.friend_requests_table_name), (from_user_email, to_user_email)) result = cursor.fetchone() cursor.close() if not result: return False return True
def technical_metrics_from_server(self, alias: str) -> TechnicalMetrics: """ Get technical metrics from a particular server :raises: UnexistentAppServer: if the alias is not associated with an app server :param alias: the alias of the app server :return: the technical metrics """ cursor = self.conn.cursor() stats = {"total": 0, 400: 0, 500: 0, "mean_time": 0.0} PostgresUtils.safe_query_run( self.logger, self.conn, cursor, GET_CALS_BY_STATUS_QUERY.format( app_server_api_calls_table=self.app_server_api_calls_table), (7, alias)) result = cursor.fetchall() if not result: raise UnexistentAppServer for r in result: stats["total"] += r[1] if r[0] == 400: stats[400] = r[1] if r[0] == 500: stats[500] = r[1] PostgresUtils.safe_query_run( self.logger, self.conn, cursor, GET_MEAN_RESPONSE_TIMES_QUERY.format( app_server_api_calls_table=self.app_server_api_calls_table), (7, alias)) result = cursor.fetchall() for r in result: stats["mean_time"] = r[0] cursor.close() return TechnicalMetrics( mean_response_time_last_7_days=stats["mean_time"], api_calls_last_7_days=stats["total"], status_500_rate_last_7_days=stats[500] / stats["total"], status_400_rate_last_7_days=stats[400] / stats["total"])
def get_conversations( self, user_email: str) -> Tuple[List[Dict], List[PrivateMessage]]: """ Get all the conversations ordered by recent activity :param user_email: the email of the user for getting the conversations :return: a tuple (list of user data, list of last private message) """ self.logger.debug("Geting last conversations with %s" % user_email) cursor = self.conn.cursor() PostgresUtils.safe_query_run( self.logger, self.conn, cursor, GET_CONVERSATIONS_QUERY.format( friends_table_name=self.friends_table_name, user_messages_table_name=self.user_messages_table_name, users_table_name=self.users_table_name, user_deleted_messages_table_name=self. user_deleted_messages_table_name), (user_email, ) * 9) ''' u.email, u.fullname, u.phone_number, u.photo messages.from_user, messages.to_user, messages.message, messages.datetime ''' result = cursor.fetchall() user_data = [{ "email": r[0], "fullname": r[1], "phone_number": r[2], "photo": r[3] } for r in result] videos_data = [ PrivateMessage(from_user=r[4], to_user=r[5], message=r[6], timestamp=r[7]) for r in result ] self.conn.commit() cursor.close() return user_data, videos_data
def __init__(self, notification_tokens_table_name: str, postgr_host_env_name: str, postgr_user_env_name: str, postgr_pass_env_name: str, postgr_database_env_name: str): self.notification_tokens_table_name = notification_tokens_table_name self.conn = PostgresUtils.get_postgres_connection( host=os.environ[postgr_host_env_name], user=os.environ[postgr_user_env_name], password=os.environ[postgr_pass_env_name], database=os.environ[postgr_database_env_name]) if self.conn.closed == 0: self.logger.info("Connected to postgres database") else: self.logger.error("Unable to connect to postgres database") raise ConnectionError("Unable to connect to postgres database")
def send_message(self, from_user_email: str, to_user_email: str, message: str) -> NoReturn: """ Sends a private message to a user :raises: UsersAreNotFriendsError: the users are not friends :param from_user_email: the email of the sender :param to_user_email: the email of the receiver :param message: the message to send """ if not self.are_friends(from_user_email, to_user_email): raise UsersAreNotFriendsError self.logger.debug("Sending user message") cursor = self.conn.cursor() PostgresUtils.safe_query_run( self.logger, self.conn, cursor, SEND_MESSAGE_QUERY.format(self.user_messages_table_name), (from_user_email, to_user_email, message, datetime.now().isoformat())) self.conn.commit() cursor.close()
def create_friend_request(self, from_user_email: str, to_user_email: str) -> NoReturn: """ Creates a friend request between :raises: UsersAlreadyFriendsError: raised when the users are already friends UnexistentTargetUserError: the target user does not exist UnexistentRequestorUserError: the user that requested the friendship does not exist :param from_user_email: the user that requests the friendship :param to_user_email: the target user of the request """ if self.are_friends(from_user_email, to_user_email): raise UsersAlreadyFriendsError self.logger.debug("Sending friend request for user with email %s" % from_user_email) cursor = self.conn.cursor() PostgresUtils.safe_query_run( self.logger, self.conn, cursor, NEW_FRIEND_REQUEST_QUERY.format(self.friend_requests_table_name), (from_user_email, to_user_email, datetime.now().isoformat())) self.conn.commit() cursor.close()
def __init__(self, app_server_api_calls_table: str, server_alias_env_name: str, postgr_host_env_name: str, postgr_user_env_name: str, postgr_pass_env_name: str, postgr_database_env_name: str): self.app_server_api_calls_table = app_server_api_calls_table self.server_alias = os.environ[server_alias_env_name] self.conn = PostgresUtils.get_postgres_connection( host=os.environ[postgr_host_env_name], user=os.environ[postgr_user_env_name], password=os.environ[postgr_pass_env_name], database=os.environ[postgr_database_env_name]) if self.conn.closed == 0: self.logger.info("Connected to postgres database") else: self.logger.error("Unable to connect to postgres database") raise ConnectionError("Unable to connect to postgres database")
def __init__(self, friends_table_name: str, friend_requests_table_name: str, user_messages_table_name: str, users_table_name: str, user_deleted_messages_table_name: str, postgr_host_env_name: str, postgr_user_env_name: str, postgr_pass_env_name: str, postgr_database_env_name: str): self.friends_table_name = friends_table_name self.friend_requests_table_name = friend_requests_table_name self.user_messages_table_name = user_messages_table_name self.users_table_name = users_table_name self.user_deleted_messages_table_name = user_deleted_messages_table_name self.conn = PostgresUtils.get_postgres_connection( host=os.environ[postgr_host_env_name], user=os.environ[postgr_user_env_name], password=os.environ[postgr_pass_env_name], database=os.environ[postgr_database_env_name]) if self.conn.closed == 0: self.logger.info("Connected to postgres database") else: self.logger.error("Unable to connect to postgres database") raise ConnectionError("Unable to connect to postgres database")