diff --git a/constants.js b/constants.js index 8ef94ff..00e1d1f 100644 --- a/constants.js +++ b/constants.js @@ -4,22 +4,16 @@ const baseAPIURL = 'https://api.spotify.com/v1'; const stateKey = 'spotify_auth_state'; const scopes = { - ImageUpload: 'ugc-image-upload', - ControlPlayback: 'user-modify-playback-state', - ViewPlaybackState: 'user-read-playback-state', - ViewCurrentlyPlaying: 'user-read-currently-playing', - ModifyFollow: 'user-follow-modify', - ViewFollow: 'user-follow-read', - ViewRecentlyPlayed: 'user-read-recently-played', - ViewPlaybackPosition: 'user-read-playback-position', - ViewTop: 'user-top-read', - ViewPrivatePlaylists: 'playlist-read-private', - IncludeCollaborative: 'playlist-read-collaborative', + // ImageUpload: 'ugc-image-upload', + AccessPrivatePlaylists: 'playlist-read-private', + AccessCollaborativePlaylists: 'playlist-read-collaborative', ModifyPublicPlaylists: 'playlist-modify-public', ModifyPrivatePlaylists: 'playlist-modify-private', - ControlRemotePlayback: 'app-remote-control', + // ModifyFollow: 'user-follow-modify', + AccessFollow: 'user-follow-read', ModifyLibrary: 'user-library-modify', - ViewLibrary: 'user-library-read' + AccessLibrary: 'user-library-read', + AccessUser: 'user-read-private', }; module.exports = { diff --git a/controllers/operations.js b/controllers/operations.js index 2dd7801..87d95e9 100644 --- a/controllers/operations.js +++ b/controllers/operations.js @@ -73,7 +73,7 @@ const updateUser = async (req, res) => { } let oldPlaylists = await Playlists.findAll({ - attributes: ["playlistID", "playlistName"], + attributes: ["playlistID"], raw: true, where: { userID: userURI.id @@ -97,6 +97,7 @@ const updateUser = async (req, res) => { let removedLinks = 0; if (toRemove.length) { + // clean up any links dependent on the playlists removedLinks = await Links.destroy({ where: { [Op.and]: [ @@ -110,6 +111,8 @@ const updateUser = async (req, res) => { ] } }) + + // only then remove const cleanedUser = await Playlists.destroy({ where: { playlistID: toRemoveIDs } }); diff --git a/controllers/playlists.js b/controllers/playlists.js index f281d2d..114c6af 100644 --- a/controllers/playlists.js +++ b/controllers/playlists.js @@ -2,7 +2,7 @@ const logger = require("../utils/logger")(module); const typedefs = require("../typedefs"); const { axiosInstance } = require('../utils/axios'); -const { parseSpotifyUri, parseSpotifyLink } = require("../utils/spotifyUriTransformer"); +const { parseSpotifyURI, parseSpotifyLink } = require("../utils/spotifyURITransformer"); /** * Retrieve list of all of user's playlists @@ -15,7 +15,7 @@ const getUserPlaylists = async (req, res) => { // get first 50 const response = await axiosInstance.get( - `/users/${parseSpotifyUri(req.session.user.uri).id}/playlists`, + `/users/${parseSpotifyURI(req.session.user.uri).id}/playlists`, { params: { offset: 0, @@ -89,7 +89,7 @@ const getPlaylistDetails = async (req, res) => { try { /** @type {typedefs.Playlist} */ let playlist = {}; - /** @type {typedefs.UriObject} */ + /** @type {typedefs.URIObject} */ let uri; let initialFields = ["collaborative", "description", "images", "name", "owner(uri,display_name)", "public", "snapshot_id", "tracks(next,total,items(is_local,track(name,uri)))"]; diff --git a/index.js b/index.js index e73d171..20ef3ed 100644 --- a/index.js +++ b/index.js @@ -64,6 +64,7 @@ app.use((_req, res) => { const port = process.env.PORT || 3000; const server = app.listen(port, () => { + logger.debug("-", { _: "_".repeat(100) }); logger.info(`App Listening on port ${port}`); }); diff --git a/typedefs.js b/typedefs.js index 037d281..e2f8548 100644 --- a/typedefs.js +++ b/typedefs.js @@ -19,7 +19,7 @@ * album?: string, * title?: string, * duration?: number - * }} UriObject + * }} URIObject * * @typedef {{ * display_name: string, diff --git a/utils/graph.js b/utils/graph.js index 5b0c85e..8dae84e 100644 --- a/utils/graph.js +++ b/utils/graph.js @@ -6,7 +6,21 @@ const typedefs = require("../typedefs"); * Directed graph, may or may not be connected. * * NOTE: Assumes that nodes and edges are valid. - */ + * + * Example: + * ```javascript + * let nodes = ['a', 'b', 'c', 'd', 'e']; + * let edges = [ + * { from: 'a', to: 'b' }, + * { from: 'b', to: 'c' }, + * { from: 'c', to: 'd' }, + * { from: 'd', to: 'a' }, + * { from: 'e', to: 'a' } + * ]; + * let g = new myGraph(nodes, edges); + * console.log(g.detectCycle()); // true + * ``` +*/ class myGraph { /** * @param {string[]} nodes Graph nodes IDs @@ -21,7 +35,15 @@ class myGraph { * @param {type} node * @returns {string[]} */ - getNeighbors(node) { + getDirectHeads(node) { + return this.edges.filter(edge => edge.to == node).map(edge => edge.from); + } + + /** + * @param {type} node + * @returns {string[]} + */ + getDirectTails(node) { return this.edges.filter(edge => edge.from == node).map(edge => edge.to); } @@ -56,10 +78,10 @@ class myGraph { let node = zeroInDegreeQueue.shift(); topologicalOrder.push(node); - for (let neighbor of this.getNeighbors(node)) { - inDegree[neighbor]--; - if (inDegree[neighbor] === 0) { - zeroInDegreeQueue.push(neighbor); + for (let tail of this.getDirectTails(node)) { + inDegree[tail]--; + if (inDegree[tail] === 0) { + zeroInDegreeQueue.push(tail); } } } diff --git a/utils/spotifyUriTransformer.js b/utils/spotifyUriTransformer.js index 8775d1a..372181c 100644 --- a/utils/spotifyUriTransformer.js +++ b/utils/spotifyUriTransformer.js @@ -7,10 +7,10 @@ const base62Pattern = /^[A-Za-z0-9]+$/; * Returns type and ID from a Spotify URI * @see {@link https://developer.spotify.com/documentation/web-api/concepts/spotify-uris-ids|Spotify URIs and IDs} * @param {string} uri Spotify URI - can be of an album, track, playlist, user, episode, etc. - * @returns {typedefs.UriObject} + * @returns {typedefs.URIObject} * @throws {TypeError} If the input is not a valid Spotify URI */ -const parseSpotifyUri = (uri) => { +const parseSpotifyURI = (uri) => { const parts = uri.split(":"); if (parts[0] !== "spotify") { @@ -56,7 +56,7 @@ const parseSpotifyUri = (uri) => { /** * Returns type and ID from a Spotify link * @param {string} link Spotify URL - can be of an album, track, playlist, user, episode, etc. - * @returns {typedefs.UriObject} + * @returns {typedefs.URIObject} * @throws {TypeError} If the input is not a valid Spotify link */ const parseSpotifyLink = (link) => { @@ -103,10 +103,10 @@ const parseSpotifyLink = (link) => { /** * Builds URI string from a URIObject - * @param {typedefs.UriObject} uriObj + * @param {typedefs.URIObject} uriObj * @returns {string} */ -const buildSpotifyUri = (uriObj) => { +const buildSpotifyURI = (uriObj) => { if (uriObj.is_local) { const artist = encodeURIComponent(uriObj.artist ?? ''); const album = encodeURIComponent(uriObj.album ?? ''); @@ -119,7 +119,7 @@ const buildSpotifyUri = (uriObj) => { /** * Builds link from a URIObject - * @param {typedefs.UriObject} uriObj + * @param {typedefs.URIObject} uriObj * @returns {string} */ const buildSpotifyLink = (uriObj) => { @@ -134,8 +134,8 @@ const buildSpotifyLink = (uriObj) => { } module.exports = { - parseSpotifyUri, + parseSpotifyURI, parseSpotifyLink, - buildSpotifyUri, + buildSpotifyURI, buildSpotifyLink }