Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#227: Add Calculated field/property for artist total streams #241

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 0 additions & 35 deletions Backend/app/spotify_electron/song/base_song_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"""

import app.spotify_electron.song.base_song_repository as base_song_repository
import app.spotify_electron.user.validations.base_user_service_validations as base_user_service_validations # noqa: E501
from app.logging.logging_constants import LOGGING_BASE_SONG_SERVICE
from app.logging.logging_schema import SpotifyElectronLogger
from app.spotify_electron.genre.genre_schema import Genre, GenreNotValidException
Expand All @@ -23,7 +22,6 @@
validate_song_name_parameter,
validate_song_should_exists,
)
from app.spotify_electron.user.user.user_schema import UserNotFoundException

base_song_service_logger = SpotifyElectronLogger(LOGGING_BASE_SONG_SERVICE).getLogger()

Expand Down Expand Up @@ -159,39 +157,6 @@ def search_by_name(name: str) -> list[SongMetadataDTO]:
return get_songs_metadata(song_names)


def get_artist_streams(artist_name: str) -> int:
"""Get artist songs total streams

Args:
artist_name (str): artist name

Raises:
UserNotFoundException: artist doesn't exists
SongServiceException: unexpected error getting artist songs total streams

Returns:
int: the number of streams for the artists songs
"""
try:
base_user_service_validations.validate_user_should_exists(artist_name)
return base_song_repository.get_artist_total_streams(artist_name)
except UserNotFoundException as exception:
base_song_service_logger.exception(f"User not found: {artist_name}")
raise UserNotFoundException from exception
except SongRepositoryException as exception:
base_song_service_logger.exception(
f"Unexpected error in Song Repository while getting "
f"total artist {artist_name} streams"
)
raise SongServiceException from exception
except Exception as exception:
base_song_service_logger.exception(
f"Unexpected error in Song Service while getting "
f"total artist {artist_name} streams"
)
raise SongServiceException from exception


def get_songs_by_genre(genre: Genre) -> list[SongMetadataDTO]:
"""Get songs by genre

Expand Down
32 changes: 0 additions & 32 deletions Backend/app/spotify_electron/user/artist/artist_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,38 +148,6 @@ def get_artists(
)


@router.get("/{name}/streams")
def get_artist_streams(
name: str,
token: Annotated[TokenData | None, Depends(JWTBearer())],
) -> Response:
"""Get artist total streams of his songs

Args:
name (str): artist name
"""
try:
total_streams = artist_service.get_streams_artist(artist_name=name)

total_streams_json = json_converter_utils.get_json_with_iterable_field_from_model(
total_streams, "streams"
)

return Response(
total_streams_json, media_type="application/json", status_code=HTTP_200_OK
)
except JsonEncodeException:
return Response(
status_code=HTTP_500_INTERNAL_SERVER_ERROR,
content=PropertiesMessagesManager.commonEncodingError,
)
except (Exception, UserServiceException):
return Response(
status_code=HTTP_500_INTERNAL_SERVER_ERROR,
content=PropertiesMessagesManager.commonInternalServerError,
)


@router.get("/{name}/songs")
def get_artist_songs(
name: str,
Expand Down
5 changes: 5 additions & 0 deletions Backend/app/spotify_electron/user/artist/artist_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from dataclasses import dataclass
from typing import Any

from app.spotify_electron.song.base_song_repository import get_artist_total_streams
from app.spotify_electron.user.user.user_schema import UserDAO, UserDTO


Expand All @@ -13,13 +14,15 @@ class ArtistDAO(UserDAO):
"""Represents artist data in the persistence layer"""

uploaded_songs: list[str]
total_streams: int = 0


@dataclass
class ArtistDTO(UserDTO):
"""Represents artist data in the endpoints transfer layer"""

uploaded_songs: list[str]
total_streams: int = 0


def get_artist_dao_from_document(document: dict[str, Any]) -> ArtistDAO:
Expand All @@ -43,6 +46,7 @@ def get_artist_dao_from_document(document: dict[str, Any]) -> ArtistDAO:
playlists=document["playlists"],
saved_playlists=document["saved_playlists"],
uploaded_songs=document["uploaded_songs"],
total_streams=get_artist_total_streams(document["name"]),
)


Expand All @@ -66,4 +70,5 @@ def get_artist_dto_from_dao(artist_dao: ArtistDAO) -> ArtistDTO:
register_date=artist_dao.register_date,
saved_playlists=artist_dao.saved_playlists,
uploaded_songs=artist_dao.uploaded_songs,
total_streams=artist_dao.total_streams,
)
47 changes: 0 additions & 47 deletions Backend/app/spotify_electron/user/artist/artist_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,53 +251,6 @@ def get_all_artists() -> list[ArtistDTO]:
return artists_dto


# TODO make it a dynamic property
def get_streams_artist(artist_name: str) -> int:
"""Get artist songs total streams

Args:
user_name (str): artist name

Raises:
UserNotFoundException: artist doesn't exists
UserBadNameException: artist bad name
UserUnauthorizedException: user is not artist
UserServiceException: unexpected error getting artist total streams

Returns:
int: the total for all artist songs
"""
try:
base_user_service_validations.validate_user_name_parameter(artist_name)
artist_service_validations.validate_user_should_be_artist(artist_name)

return base_song_service.get_artist_streams(artist_name)
except UserNotFoundException as exception:
artist_service_logger.exception(f"Artist not found: {artist_name}")
raise UserNotFoundException from exception
except UserBadNameException as exception:
artist_service_logger.exception(f"Bad Artist Name Parameter: {artist_name}")
raise UserBadNameException from exception
except UserUnauthorizedException as exception:
artist_service_logger.exception(f"User {artist_name} is not Artist")
raise UserUnauthorizedException from exception
except UserRepositoryException as exception:
artist_service_logger.exception(
f"Unexpected error in Artist Repository getting artist: {artist_name}"
)
raise UserServiceException from exception
except SongServiceException as exception:
artist_service_logger.exception(
f"Unexpected error in Song Service getting artist: {artist_name}"
)
raise UserServiceException from exception
except Exception as exception:
artist_service_logger.exception(
f"Unexpected error in Artist Service getting artist: {artist_name}"
)
raise UserServiceException from exception


# TODO obtain all users in same query
def get_artists(user_names: list[str]) -> list[ArtistDTO]:
"""Get artists from a list of names
Expand Down
4 changes: 0 additions & 4 deletions Backend/tests/test_API/api_test_artist.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,5 @@ def get_artists(headers: dict[str, str]) -> Response:
return client.get("/artists/", headers=headers)


def get_artist_streams(name: str, headers: dict[str, str]) -> Response:
return client.get(f"/artists/{name}/streams", headers=headers)


def get_artist_songs(name: str, headers: dict[str, str]) -> Response:
return client.get(f"/artists/{name}/songs", headers=headers)
47 changes: 22 additions & 25 deletions Backend/tests/test__artist.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
HTTP_200_OK,
HTTP_201_CREATED,
HTTP_202_ACCEPTED,
HTTP_204_NO_CONTENT,
HTTP_403_FORBIDDEN,
HTTP_404_NOT_FOUND,
HTTP_405_METHOD_NOT_ALLOWED,
Expand All @@ -15,7 +14,6 @@
create_artist,
get_artist,
get_artist_songs,
get_artist_streams,
get_artists,
)

Expand Down Expand Up @@ -125,56 +123,55 @@ def test_get_artists_correct():


def test_get_total_streams_artist_correct(clear_test_data_db):
song_name = "8232392323623823723989"
song_name_1 = "8232392323623823723989"
song_name_2 = "82323923236238237239892"
file_path = "tests/assets/song.mp3"
artista = "8232392323623823723"
artist_name = "8232392323623823723"
genre = "Pop"
photo = "https://photo"
password = "hola"

res_create_artist = create_artist(name=artista, password=password, photo=photo)
res_create_artist = create_artist(name=artist_name, password=password, photo=photo)
assert res_create_artist.status_code == HTTP_201_CREATED

jwt_headers = get_user_jwt_header(username=artista, password=password)
jwt_headers = get_user_jwt_header(username=artist_name, password=password)

res_create_song = create_song(
name=song_name,
res_create_song_1 = create_song(
name=song_name_1,
file_path=file_path,
genre=genre,
photo=photo,
headers=jwt_headers,
)
assert res_create_song.status_code == HTTP_201_CREATED
assert res_create_song_1.status_code == HTTP_201_CREATED

res_create_song = create_song(
res_create_song_2 = create_song(
name=song_name_2,
file_path=file_path,
genre=genre,
photo=photo,
headers=jwt_headers,
)
assert res_create_song.status_code == HTTP_201_CREATED
assert res_create_song_2.status_code == HTTP_201_CREATED

expected_artist_total_streams = 2
increase_song_streams(name=song_name_1, headers=jwt_headers)
increase_song_streams(name=song_name_2, headers=jwt_headers)

res_increase_streams_song = increase_song_streams(name=song_name, headers=jwt_headers)
assert res_increase_streams_song.status_code == HTTP_204_NO_CONTENT

res_increase_streams_song = increase_song_streams(name=song_name_2, headers=jwt_headers)
assert res_increase_streams_song.status_code == HTTP_204_NO_CONTENT
res_get_artist = get_artist(name=artist_name, headers=jwt_headers)
assert res_get_artist.status_code == HTTP_200_OK

res_get_total_streams_artist = get_artist_streams(artista, headers=jwt_headers)
assert res_get_total_streams_artist.status_code == HTTP_200_OK
assert res_get_total_streams_artist.json()["streams"] == expected_artist_total_streams
artist_data = res_get_artist.json()
expected_total_streams = 2
assert "total_streams" in artist_data
assert artist_data["total_streams"] == expected_total_streams

res_delete_song = delete_song(song_name)
assert res_delete_song.status_code == HTTP_202_ACCEPTED
res_delete_song_1 = delete_song(song_name_1)
assert res_delete_song_1.status_code == HTTP_202_ACCEPTED

res_delete_song = delete_song(song_name_2)
assert res_delete_song.status_code == HTTP_202_ACCEPTED
res_delete_song_2 = delete_song(song_name_2)
assert res_delete_song_2.status_code == HTTP_202_ACCEPTED

res_delete_artist = delete_user(artista)
res_delete_artist = delete_user(artist_name)
assert res_delete_artist.status_code == HTTP_202_ACCEPTED


Expand Down
17 changes: 2 additions & 15 deletions Electron/src/__tests__/pages/UserProfile.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ test('UserProfile Artist load Songs and total streams', async () => {
playlists: [playlistName],
saved_playlists: [playlistName],
uploaded_songs: [songName],
total_streams: 190,
};

const playlistDTOMockFetch = {
Expand All @@ -160,7 +161,7 @@ test('UserProfile Artist load Songs and total streams', async () => {
photo: 'photo',
seconds_duration: '3',
genre: 'Rock',
streams: 2,
streams: artistMockFetch.total_streams,
};

jest.mock('react-router-dom', () => ({
Expand All @@ -181,20 +182,6 @@ test('UserProfile Artist load Songs and total streams', async () => {
console.log(error);
});
}
if (
url === `${Global.backendBaseUrl}/artists/${artistMockFetch.name}/streams`
) {
return Promise.resolve({
json: () => ({
streams: songMockFetch.streams,
}),
status: 200,
ok: true,
headers: getMockHeaders(),
}).catch((error) => {
console.log(error);
});
}
if (
url === `${Global.backendBaseUrl}/artists/${artistMockFetch.name}/songs`
) {
Expand Down
12 changes: 1 addition & 11 deletions Electron/src/pages/UserProfile/UserProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,6 @@ export default function UserProfile({
const { playlists } = useFetchGetUserPlaylists(id);

useEffect(() => {
const loadArtistsStreams = async (userName: string) => {
try {
const artistData =
await ArtistsService.getArtistStreamsArtistsNameStreamsGet(userName);
setArtistStreams(artistData.streams);
} catch (error) {
setArtistStreams(0);
console.log(`Unable to get streams from artist ${id}`);
}
};
const loadPlaybackHistory = async (userName: string) => {
try {
const playbackHistoryData =
Expand Down Expand Up @@ -75,8 +65,8 @@ export default function UserProfile({
if (userType === UserType.USER) {
loadPlaybackHistory(userName);
} else if (userType === UserType.ARTIST) {
setArtistStreams(userData.total_streams);
loadSongsFromArtist(userName);
loadArtistsStreams(userName);
}
};
if (!id) return;
Expand Down
24 changes: 0 additions & 24 deletions Electron/src/swagger/api/services/ArtistsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,30 +74,6 @@ export class ArtistsService {
url: '/artists/',
});
}
/**
* Get Artist Streams
* Get artist total streams of his songs
*
* Args:
* name (str): artist name
* @param name
* @returns any Successful Response
* @throws ApiError
*/
public static getArtistStreamsArtistsNameStreamsGet(
name: string,
): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/artists/{name}/streams',
path: {
'name': name,
},
errors: {
422: `Validation Error`,
},
});
}
/**
* Get Artist Songs
* Get artist songs
Expand Down
Loading