From 10e9020f312b8e793e624aadde1ef5e2058418d2 Mon Sep 17 00:00:00 2001 From: Kaushik Narayan R Date: Sun, 24 Sep 2023 23:45:05 -0700 Subject: [PATCH] get playlist details (first 100 tracks) --- controllers/auth.js | 2 +- controllers/playlists.js | 59 +++++++++++++++++++++++++++++++------- routes/playlists.js | 8 +++++- typedefs.js | 45 +++++++++++++++++++++++++++++ axios.js => utils/axios.js | 4 +-- 5 files changed, 103 insertions(+), 15 deletions(-) rename axios.js => utils/axios.js (92%) diff --git a/controllers/auth.js b/controllers/auth.js index d47e8fd..03a5c46 100644 --- a/controllers/auth.js +++ b/controllers/auth.js @@ -1,4 +1,4 @@ -const { authInstance } = require("../axios"); +const { authInstance } = require("../utils/axios"); const typedefs = require("../typedefs"); const { scopes, stateKey, accountsAPIURL } = require('../constants'); diff --git a/controllers/playlists.js b/controllers/playlists.js index 1f828d4..c1fbf1b 100644 --- a/controllers/playlists.js +++ b/controllers/playlists.js @@ -1,7 +1,7 @@ const logger = require("../utils/logger")(module); const typedefs = require("../typedefs"); -const { axiosInstance } = require('../axios'); +const { axiosInstance } = require('../utils/axios'); /** * Retrieve list of all of user's playlists @@ -26,15 +26,12 @@ const getUserPlaylists = async (req, res) => { } ); + /** @type {typedefs.SimplifiedPlaylist[]} */ playlists.items = response.data.items.map((playlist) => { return { name: playlist.name, description: playlist.description, owner: playlist.owner.display_name, - images: playlist.images.map((image) => image.url), - link: playlist.external_urls.spotify, - collaborative: playlist.collaborative, - public: playlist.public, id: playlist.id, } }); @@ -59,10 +56,6 @@ const getUserPlaylists = async (req, res) => { name: playlist.name, description: playlist.description, owner: playlist.owner.display_name, - images: playlist.images.map((image) => image.url), - link: playlist.external_urls.spotify, - collaborative: playlist.collaborative, - public: playlist.public, id: playlist.id, } }) @@ -73,11 +66,55 @@ const getUserPlaylists = async (req, res) => { return res.status(200).send(playlists); } catch (error) { - logger.error('Error', { error }); + logger.error('getUserPlaylists', { error }); return res.status(500).send({ message: "Server Error. Try again." }); } } +/** + * Retrieve single playlist + * @param {typedefs.Req} req + * @param {typedefs.Res} res + */ +const getUserPlaylist = async (req, res) => { + try { + /** @type {typedefs.Playlist} */ + let playlist = {}; + + const response = await axiosInstance.get( + "/playlists/" + req.query.playlist_id, + { + headers: { ...req.authHeader } + } + ); + + // TODO: this whole section needs to be DRYer + playlist.uri = response.data.uri + playlist.name = response.data.name + playlist.description = response.data.description + let { display_name, uri, id, ...rest } = response.data.owner + playlist.owner = { display_name, uri, id } + playlist.followers = response.data.followers.total + playlist.tracks = response.data.tracks.items.map((playlist_track) => { + return { + added_at: playlist_track.added_at, + track: { + uri: playlist_track.track.uri, + name: playlist_track.track.name, + artists: playlist_track.track.artists.map((artist) => { return { name: artist.name } }), + album: { name: playlist_track.track.album.name }, + is_local: playlist_track.track.is_local, + } + } + }); + + return res.status(200).send(playlist); + } catch (error) { + logger.error('getUserPlaylist', { error }); + return res.status(500).send({ message: "Server Error. Try again." }); + } +} module.exports = { - getUserPlaylists + getUserPlaylists, + getUserPlaylist, }; \ No newline at end of file diff --git a/routes/playlists.js b/routes/playlists.js index 5ee784b..f92c6dc 100644 --- a/routes/playlists.js +++ b/routes/playlists.js @@ -1,6 +1,6 @@ const router = require('express').Router(); -const { getUserPlaylists } = require('../controllers/playlists'); +const { getUserPlaylists, getUserPlaylist } = require('../controllers/playlists'); const { isAuthenticated } = require('../middleware/authCheck'); const validator = require("../validators"); @@ -10,5 +10,11 @@ router.get( validator.validate, getUserPlaylists ); +router.get( + "/details", + isAuthenticated, + validator.validate, + getUserPlaylist +); module.exports = router; diff --git a/typedefs.js b/typedefs.js index e494f32..743cd13 100644 --- a/typedefs.js +++ b/typedefs.js @@ -6,6 +6,51 @@ * @typedef {import('express').NextFunction} Next * * @typedef {import('winston').Logger} Logger + * + * @typedef {{ + * display_name: string, + * uri: string, + * id: string + * }} PlaylistOwner + * + * @typedef {{ + * name: string, + * description: string, + * owner: PlaylistOwner, + * id: string, + * }} SimplifiedPlaylist + * + * @typedef {{ + * name: string + * }} Album + * + * @typedef {{ + * name: string + * }} Artist + * + * @typedef {{ + * uri: string, + * name: string, + * artists: Artist[] + * album: Album, + * is_local: boolean, + * }} Track + * + * @typedef {{ + * added_at: string, + * track: Track, + * }} PlaylistTrack + * + * @typedef {{ + * uri: string, + * name: string, + * description: string, + * owner: PlaylistOwner, + * followers: { + * total: number + * }, + * tracks: PlaylistTrack[], + * }} Playlist */ exports.unused = {}; \ No newline at end of file diff --git a/axios.js b/utils/axios.js similarity index 92% rename from axios.js rename to utils/axios.js index bca1ca5..26b5f2d 100644 --- a/axios.js +++ b/utils/axios.js @@ -1,7 +1,7 @@ const axios = require('axios'); -const { baseAPIURL, accountsAPIURL } = require("./constants"); -const logger = require('./utils/logger')(module); +const { baseAPIURL, accountsAPIURL } = require("../constants"); +const logger = require('./logger')(module); const authInstance = axios.default.create({ baseURL: accountsAPIURL,