import { dbPromise } from './database' async function getPlaylist (id, order = 'ntry.indx', direction = 'ASC') { const db = await dbPromise const p = await db.get('SELECT * FROM Playlist WHERE id = ?', id) if (!p) throw new Error('No such playlist!') const q = await db.all(`SELECT ntry.id,ntry.trackId,ntry.playlistId,ntry.indx,ntry.userId, trck.title,trck.artist,trck.genre,trck.year,trck.duration,trck.track,trck.album FROM PlaylistEntry ntry INNER JOIN Track trck ON ntry.trackId = trck.id WHERE ntry.playlistId = ? ORDER BY ${order} ${direction}`, id) p.tracks = q || [] return p } async function getPlaylists (userId) { const db = await dbPromise return db.all('SELECT * FROM Playlist WHERE userId = ? OR userId = NULL', userId) } async function createPlaylist (userId, title) { const db = await dbPromise const alreadyExists = await db.get('SELECT * FROM Playlist WHERE userId = ? AND title = ?', userId, title) if (alreadyExists) throw new Error('Playlist with the same name already exists!') await db.run('INSERT INTO Playlist (title,userId) VALUES (?,?)', title, userId) return db.get('SELECT id FROM Playlist WHERE title = ? AND userId = ?', title, userId) } async function deletePlaylist (userId, playlistId) { const db = await dbPromise const ply = await db.get('SELECT * FROM Playlist WHERE id = ?', playlistId) if (!ply) throw new Error('Could not find playlist specified.') if (ply.userId !== userId) throw new Error(ply.userId == null ? 'This public playlist cannot be deleted through the interface.' : 'Permission denied.') db.run('DELETE Playlist WHERE id = ?', playlistId) db.run('DELETE PlaylistEntry WHERE playlistId = ?', playlistId) return true } async function addTrack (userId, playlistId, trackId) { const db = await dbPromise const p = await getPlaylist(playlistId) if (!p) throw new Error('Invalid playlist.') if (p.userId != null && p.userId !== userId) throw new Error('Permission denied.') let alreadyExists = false for (const i in p.tracks) { const tr = p.tracks[i] if (tr.trackId === parseInt(trackId)) { alreadyExists = true break } } if (alreadyExists) throw new Error('This track is already in the playlist.') return db.run('INSERT INTO PlaylistEntry (playlistId,trackId,userId,indx) VALUES (?,?,?,?)', playlistId, trackId, userId, p.tracks.length) } async function removeTrack (userId, playlistId, trackId) { const db = await dbPromise const p = await getPlaylist(playlistId) if (!p) throw new Error('Invalid playlist.') if (p.userId != null && p.userId !== userId) throw new Error('Permission denied.') const trackEntry = await db.get('SELECT * FROM PlaylistEntry WHERE playlistId = ? AND trackId = ?', playlistId, trackId) if (!trackEntry) throw new Error('This track is not in the playlist.') return db.run('DELETE FROM PlaylistEntry WHERE id = ?', trackEntry.id) } async function moveTrack (userId, playlistId, trackId, position) { const db = await dbPromise const p = await getPlaylist(playlistId) if (!p) throw new Error('Invalid playlist.') if (p.userId != null && p.userId !== userId) throw new Error('Permission denied.') const trackEntry = await db.get('SELECT * FROM PlaylistEntry WHERE playlistId = ? AND trackId = ?', playlistId, trackId) if (!trackEntry) throw new Error('This track is not in the playlist.') const trcksNew = [] for (const i in p.tracks) { const trck = p.tracks[i] if (trck.trackId === trackId) { trck.indx = position continue } if (trck.indx >= position) { trck.indx++ } trcksNew.push(trck) } // Update indexes for (const i in trcksNew) { const trck = trcksNew[i] await db.run('UPDATE PlaylistEntry SET indx = ? WHERE trackId = ? AND playlistId = ?', trck.indx, trck.trackId, playlistId) } return true } export { getPlaylist, getPlaylists, createPlaylist, deletePlaylist, addTrack, removeTrack, moveTrack }