-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add playlist selector and ability to add and remove from playlists
- Loading branch information
Showing
14 changed files
with
444 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { checkAuthenticated } from "@/util/api"; | ||
import { getDB } from "@/util/db"; | ||
import { NextResponse } from "next/server"; | ||
|
||
// POST /playlist/[playlistId]/add-track | ||
// Add a track to the playlist | ||
// Request body: | ||
// { trackId } | ||
|
||
export async function POST(request: Request, { params }: { params: { playlistId: string } }) { | ||
const playlistId = params.playlistId; | ||
const { trackId } = await request.json(); | ||
|
||
// check authorization | ||
const tokenUuid = await checkAuthenticated(); | ||
if (tokenUuid === null) { | ||
return NextResponse.json({ error: "not authorized" }, { status: 401 }); | ||
} | ||
|
||
const conn = await getDB(); | ||
|
||
try { | ||
// check if playlist exists | ||
const playlistRes = await conn.query(` | ||
SELECT id FROM playlist WHERE id = $1 AND account_uuid = $2 | ||
`, [playlistId, tokenUuid]); | ||
|
||
if (playlistRes.rowCount === 0) { | ||
await conn.end(); | ||
return NextResponse.json({ error: "playlist not found or not authorized to update" }, { status: 404 }); | ||
} | ||
|
||
// check if track exists | ||
const trackRes = await conn.query(` | ||
SELECT id FROM track WHERE id = $1 AND account_uuid = $2 | ||
`, [trackId, tokenUuid]); | ||
|
||
if (trackRes.rowCount === 0) { | ||
await conn.end(); | ||
return NextResponse.json({ error: 'track not found' }, { status: 404 }); | ||
} | ||
|
||
// check how many tracks there are | ||
const trackCountRes = await conn.query(` | ||
SELECT COUNT(*) FROM playlist_tracks WHERE playlist_id = $1 | ||
`, [playlistId]); | ||
|
||
const trackCount = trackCountRes.rows[0].count; | ||
|
||
// insert the track association | ||
await conn.query( | ||
` | ||
INSERT INTO playlist_tracks(account_uuid, playlist_id, track_id, position, added_on) | ||
VALUES ( | ||
$1, | ||
$2, | ||
$3, | ||
$4, | ||
$5 | ||
) | ||
`, | ||
[tokenUuid, playlistId, trackId, trackCount, new Date().toISOString()] | ||
); | ||
|
||
await conn.end(); | ||
|
||
return NextResponse.json({ status: 'success' }, { status: 200 }); | ||
} catch (error) { | ||
await conn.end(); | ||
console.error("Error updating playlist:", error); | ||
return NextResponse.json({ error: 'an error occurred while updating the playlist' }, { status: 500 }); | ||
} | ||
} |
105 changes: 105 additions & 0 deletions
105
website/app/api/playlist/[playlistId]/remove-track/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import { checkAuthenticated } from "@/util/api"; | ||
import { getDB } from "@/util/db"; | ||
import { DBPlaylistTrack } from "@/util/models/playlist"; | ||
import { NextResponse } from "next/server"; | ||
|
||
// POST /playlist/[playlistId]/remove-track | ||
// Add a track to the playlist | ||
// Request body: | ||
// { position } or { trackId } | ||
|
||
export async function POST(request: Request, { params }: { params: { playlistId: string } }) { | ||
const playlistId = params.playlistId; | ||
let { position, trackId } = await request.json(); | ||
|
||
if (position === undefined && trackId === undefined) { | ||
return NextResponse.json({ error: 'invalid query' }, { status: 400 }); | ||
} | ||
|
||
// check authorization | ||
const tokenUuid = await checkAuthenticated(); | ||
if (tokenUuid === null) { | ||
return NextResponse.json({ error: "not authorized" }, { status: 401 }); | ||
} | ||
|
||
const conn = await getDB(); | ||
|
||
try { | ||
// check if playlist exists | ||
const playlistRes = await conn.query(` | ||
SELECT id FROM playlist WHERE id = $1 AND account_uuid = $2 | ||
`, [playlistId, tokenUuid]); | ||
|
||
if (playlistRes.rowCount === 0) { | ||
await conn.end(); | ||
return NextResponse.json({ error: "playlist not found or not authorized to update" }, { status: 404 }); | ||
} | ||
|
||
// check how many tracks there are | ||
const tracksRes = await conn.query(` | ||
SELECT * FROM playlist_tracks WHERE playlist_id = $1 | ||
`, [playlistId]); | ||
|
||
const trackCount = tracksRes.rowCount; | ||
|
||
// check that the requested deletion position is in bounds | ||
if (position !== undefined && (position >= trackCount || position < 0)) { | ||
await conn.end(); | ||
return NextResponse.json({ error: 'position out of bounds' }, { status: 400 }) | ||
} | ||
|
||
await conn.query(`BEGIN`); | ||
|
||
// delete entry | ||
if (trackId !== undefined) { | ||
|
||
// HACK: we assume that there is only one occurrence of the track in the playlist, which is true for now... | ||
|
||
const deleteRes = await conn.query(` | ||
DELETE FROM playlist_tracks | ||
WHERE playlist_id = $1 AND track_id = $2 | ||
RETURNING * | ||
`, [playlistId, trackId]); | ||
|
||
// if the track wasn't found | ||
if (deleteRes.rowCount === 0) { | ||
await conn.query(`COMMIT`); | ||
await conn.end(); | ||
return NextResponse.json({ error: 'track not found in playlist' }, { status: 404 }); | ||
} | ||
|
||
// add the position it was deleted at | ||
position = deleteRes.rows[0].position; | ||
|
||
} else { | ||
await conn.query(` | ||
DELETE FROM playlist_tracks WHERE playlist_id = $1 AND position = $2 | ||
`, [playlistId, position]); | ||
} | ||
|
||
const playlistTracks = tracksRes.rows as DBPlaylistTrack[]; | ||
|
||
// update other entries (all position spots after) | ||
for (const playlistTrack of playlistTracks) { | ||
if (playlistTrack.position > position) { | ||
|
||
await conn.query(` | ||
UPDATE playlist_tracks SET position = $1 WHERE playlist_id = $2 AND position = $3 AND track_id = $4 | ||
`, [playlistTrack.position - 1, playlistId, playlistTrack.position, playlistTrack.track_id]); | ||
|
||
} | ||
} | ||
|
||
await conn.query(`COMMIT`); | ||
await conn.end(); | ||
|
||
return NextResponse.json({ status: 'success' }, { status: 200 }); | ||
} catch (error) { | ||
|
||
await conn.query(`ROLLBACK`); | ||
|
||
await conn.end(); | ||
console.error("Error updating playlist:", error); | ||
return NextResponse.json({ error: 'an error occurred while updating the playlist' }, { status: 500 }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.