Spotify2 is a remake of the original Spotify application with the same functionality. Logged-in users can upload songs, create albums and playlists, and like songs while everyone can play songs.
https://spotify2-b6rv.onrender.com
Python, Flask, JavaScript, React, Redux, CSS3, HTML5
Postgres
Render
All patch, posts and deletes have @login_required and/or flask_login's current_user associated with them for proper authentication that the user is in fact the owner of the post or review and that there is a user.
- Purpose: Checks whether the user is authenticated and returns that users information
- Method: GET
- URL: /api/auth/
- Response:
{
id: 1,
username: "demo-lition",
email: "demo@aa.io"
}
- Error Response: Status code 401
{'errors': {'message': 'Unauthorized'}}
- Purpose: Logs in a user with the email and password combo
- Method: POST
- URL: /api/auth/login
- Response:
{
id: 1,
username: "demo-lition",
email: "demo@aa.io"
}
- Error Response: Status code 401
{'errors': 'different error messages for incorrect password or email or invalid login'}
- Purpose: Logout a signed in user
- Method: GET
- URL: /api/auth/logout
- Response:
{
'message': 'User logged out'
}
- Purpose: Lets a user sign up for a new account and returns new user's data
- Method: POST
- URL: /api/auth/signup
- Response:
{
id: 1,
username: "demo-lition",
email: "demo@aa.io"
}
- Error Response: Status code 401
{'errors': 'different error messages for improper email and password '}
- Purpose: Returns unauthorized JSON when flask-login authentication fails
- Method: GET
- URL: /api/auth/
- Response: 401
{'errors': {'message': 'Unauthorized'}}
- Purpose: Returns data for all users
- Method: GET
- URL: /api/users/
- Response:
{'users': [
{
id: 1,
username: "demo-lition",
email: "demo@aa.io"
},
{
id: 2,
username: "Terry",
email: "terry23@aa.io"
}
]
}
- Purpose: Returns a specific user's data
- Method: GET
- URL: /api/users/:userId
- Response:
{
id: 1,
username: "demo-lition",
email: "demo@aa.io"
}
- Purpose: Returns a list of all songs and their likes
- Method: GET
- URL: /api/songs/
- Response:
[
{
id: 23,
title: "The Title of song",
url: "www.a-url-for-the-song.com",
artist_id: 2,
genre: 'rap',
album: 'The album name',
likes: [
{
id: 1,
artist_id: 7,
song_id: 23,
liked_at: 2025-01-30 12:00:00
},
{
id: 2,
artist_id: 3,
song_id: 23,
liked_at: 2025-01-30 12:00:00
}
],
created_at: 2025-01-30 12:00:00,
updated_at: 2025-01-30 12:00:00
},
{
id: 26,
title: "The Title of song part 2",
url: "www.a-url-for-the-song-part-2.com",
artist_id: 8,
genre: 'pop',
album: 'The album name part 2',
likes: [
{
id: 1,
artist_id: 4,
song_id: 26,
liked_at: 2025-01-30 12:00:00
},
{
id: 2,
artist_id: 10,
song_id: 26,
liked_at: 2025-01-30 12:00:00
}
],
created_at: 2025-01-30 12:00:00,
updated_at: 2025-01-30 12:00:00
},
]
- Purpose: Get a specific song
- Method: GET
- URL: /api/songs/:songId
- Response:
{
id: 23,
title: "The Title of song",
url: "www.a-url-for-the-song.com",
artist_id: 2,
genre: 'rap',
album: 'The album name',
likes: [
{
id: 1,
artist_id: 7,
song_id: 23,
liked_at: 2025-01-30 12:00:00
},
{
id: 2,
artist_id: 3,
song_id: 23,
liked_at: 2025-01-30 12:00:00
}
],
created_at: 2025-01-30 12:00:00,
updated_at: 2025-01-30 12:00:00
}
- Error Response:
{'errors': {'message': "Couldn't find song"}} 404
- Purpose: A logged in user can add a song
- Method: POST
- URL: /api/songs/upload-song
- Response:
{
id: 23,
title: "The Title of song",
url: "www.a-url-for-the-song.com",
artist_id: 2,
genre: 'rap',
album: 'The album name',
likes: [],
created_at: 2025-01-30 12:00:00,
updated_at: 2025-01-30 12:00:00
}
- Error Response:
{'error': 'Various errors that might be brought up from the form submission'} 400
- Purpose: A logged in user can edit/update a song if it is theirs
- Method: PUT
- URL: /api/songs/:songId
- Response:
{
id: 23,
title: "The Title of song",
url: "www.a-url-for-the-song.com",
artist_id: 2,
genre: 'rap',
album: 'The album name',
likes: [],
created_at: 2025-01-30 12:00:00,
updated_at: 2025-01-30 12:00:00
}
- Error Response:
{'errors': {'message': "Couldn't find song"}}, 404
{'errors': {'message': 'Unauthorized'}}, 401
{'error': 'Various errors that might be brought up from the form submission'} 400
- Purpose:
- Method: DELETE
- URL: /api/songs/:songId
- Response:
{"message": "Song deleted successfully"}
- Error Response:
{"error": {"Song not found"}}, 404
{"errors": "Failed to remove the file from S3"}, 500
{"error": {"You do not have permission to delete this song"}}, 403
- Purpose: A logged in user can like a song
- Method: POST
- URL: /api/songs/:songId/likes
- Response:
{'message': "Success"}
- Purpose: A logged in user can unlike a song
- Method: DELETE
- URL: /api/songs/:songId/likes
- Response:
{'message': "Successfully deleted"}
- Error Response:
{"error": {"You do not have permission to delete this like"}}, 403
{"error": {"Like not found"}}, 404
- Purpose: Get all playlists for the current user
- Method: GET
- URL: /api/users/playlists/test
- Response:
[
{
id: 1
name: 'playlist name 1'
user_id: 1
songs: [
{
id: 23,
title: "The Title of song",
url: "www.a-url-for-the-song.com",
artist_id: 2,
genre: 'rap',
album: 'The album name',
likes: [],
created_at: 2025-01-30 12:00:00,
updated_at: 2025-01-30 12:00:00
},
{
id: 24,
title: "The Title of song2",
url: "www.a-url-for-the-song2.com",
artist_id: 3,
genre: 'rap',
album: 'The album name2',
likes: [],
created_at: 2025-01-30 12:00:00,
updated_at: 2025-01-30 12:00:00
}
]
},
{
id: 2
name: 'playlist name 2'
user_id: 1
songs: [
{
id: 23,
title: "The Title of song",
url: "www.a-url-for-the-song.com",
artist_id: 2,
genre: 'rap',
album: 'The album name',
likes: [],
created_at: 2025-01-30 12:00:00,
updated_at: 2025-01-30 12:00:00
},
{
id: 24,
title: "The Title of song2",
url: "www.a-url-for-the-song2.com",
artist_id: 3,
genre: 'rap',
album: 'The album name2',
likes: [],
created_at: 2025-01-30 12:00:00,
updated_at: 2025-01-30 12:00:00
}
]
}
]
- Purpose: Get a single playlist by ID if it belongs to current user
- Method: GET
- URL: /api/users/playlists/:playlistId
- Response:
{
id: 1
name: 'playlist name 1'
user_id: 1
songs: [
{
id: 23,
title: "The Title of song",
url: "www.a-url-for-the-song.com",
artist_id: 2,
genre: 'rap',
album: 'The album name',
likes: [],
created_at: 2025-01-30 12:00:00,
updated_at: 2025-01-30 12:00:00
},
{
id: 24,
title: "The Title of song2",
url: "www.a-url-for-the-song2.com",
artist_id: 3,
genre: 'rap',
album: 'The album name2',
likes: [],
created_at: 2025-01-30 12:00:00,
updated_at: 2025-01-30 12:00:00
}
]
}
- Error Response:
{'error': 'Playlist not found'}, 404
- Purpose: Create a new Playlist for the current user
- Method: POST
- URL: /api/user/playlists/test
- Response:
{
id: 1
name: 'playlist name 1'
user_id: 1
songs: []
}
- Error Response:
{'error': 'Various errors that might be brought up from the form submission'} 400
- Purpose: Delete a playlist if the user owns it
- Method: DELETE
- URL: /api/user/playlists/:playlistId
- Response:
{'message': 'Playlist deleted successfully'}
- Error Response:
{'error': 'Playlist not found'}, 404
{'error': 'You do not have permission to delete this playlist'}, 403
- Purpose: Add a song to an existing playlist
- Method: POST
- URL: /api/user/playlists/:playlistId/songs/:songId
- Response:
{'message': 'Song added to playlist', 'playlist':{
id: 1
name: 'playlist name 1'
user_id: 1
songs: [
{
id: 24,
title: "The Title of song2",
url: "www.a-url-for-the-song2.com",
artist_id: 3,
genre: 'rap',
album: 'The album name2',
likes: [],
created_at: 2025-01-30 12:00:00,
updated_at: 2025-01-30 12:00:00
}]
}}
- Error Response:
{'error': 'Playlist not found'}, 404
{'error': 'Song not found'}, 404
- Purpose: Remove a song from an existing playlist
- Method: DELETE
- URL: /api/user/playlists/:playlistId/songs/:songId
- Response:
{'message': 'Song removed to playlist', 'playlist':{
id: 1
name: 'playlist name 1'
user_id: 1
songs: []
}}
- Error Response:
{'error': 'Playlist not found'}, 404
{'error': 'Song not found'}, 404
{'error': 'Song is not in the specified playlist'}, 404
{'error': 'You do not have permission to remove songs from this playlist'}, 403
- Purpose: Get all the albums
- Method: GET
- URL: /api/albums/
- Response:
{
albums: [
{
id: 1,
title: 'Something to say',
artist_id: 1
},
{
id: 2,
title: 'Something to say2',
artist_id: 2
},
{
id: 3,
title: 'Something to say3',
artist_id: 3
},
{
id: 4,
title: 'Something to say4',
artist_id: 4
},
]
}
- Purpose: Get a specific album
- Method: GET
- URL: /api/albums/:albumId
- Response:
{
id: 1,
title: 'Something to say',
artist_id: 1,
song: [
{
id: 23,
title: "The Title of song",
url: "www.a-url-for-the-song.com",
artist_id: 2,
genre: 'rap',
album: 'The album name',
likes: [],
created_at: 2025-01-30 12:00:00,
updated_at: 2025-01-30 12:00:00
},
{
id: 24,
title: "The Title of song2",
url: "www.a-url-for-the-song2.com",
artist_id: 3,
genre: 'rap',
album: 'The album name2',
likes: [],
created_at: 2025-01-30 12:00:00,
updated_at: 2025-01-30 12:00:00
}
]
}
- Error Response:
{'error': 'Album does not exist'}, 404
- Purpose: Update specific album
- Method: PATCH
- URL: /api/albums/:albumId
- Response:
{'message': 'Successfully changed album name'}
- Error Response:
{'error': 'Album does not exist'}, 404
{'error': 'Album does not belong to you'}, 401
{'error': 'Various errors that might be brought up from the form submission'}, 400
- Purpose: Create an album for the current user
- Method: POST
- URL: /api/albums/create-album
- Response:
{'message': Album {album.title} was created'}
- Error Response:
{'error': 'Various errors that might be brought up from the form submission'}, 400
- Purpose: Delete a specific album
- Method: DELETE
- URL: /api/albums/:albumId
- Response:
{"message": "Deleted album"}
- Error Response:
{'error': 'Album does not exist'}, 404
{'error': 'Album does not belong to you'}, 401
- Purpose: Add a song to an album
- Method: POST
- URL: /api/albums/:albumId/song/:songId
- Response:
{'message': '{song.title} added to {album.title}'}
- Error Response:
{'error': 'This song is already added to this album'}, 409
{'error': 'Song does not belong to you'}, 403
{'error': 'Song does not exist'}, 404
{'error': 'Album does not belong to you'}, 403
{'error': 'Album does not exist} 404
- Purpose: Add a song to an album
- Method: DELETE
- URL: /api/albums/:albumId/song/:songId
- Response:
{'message': '{song.title} was removed from {album.title}'}
- Error Response:
{'error': 'Song is not part of the album'}, 404
{'error': 'Song does not belong to the current user'}, 403
{'error': 'No song was found'}, 404
{'error': 'Album does not belong to you'}, 403
{'error': 'No album was found'}, 404