import express from "express"; import pool from "../lib/db.js"; const router = express.Router(); // 앨범 상세 정보 조회 헬퍼 함수 (트랙, 티저, 컨셉포토 포함) async function getAlbumDetails(album) { // 트랙 정보 조회 (가사 포함) const [tracks] = await pool.query( "SELECT * FROM tracks WHERE album_id = ? ORDER BY track_number", [album.id] ); album.tracks = tracks; // 티저 이미지/비디오 조회 (3개 해상도 URL + video_url + media_type 포함) const [teasers] = await pool.query( "SELECT original_url, medium_url, thumb_url, video_url, media_type FROM album_teasers WHERE album_id = ? ORDER BY sort_order", [album.id] ); album.teasers = teasers; // 컨셉 포토 조회 (멤버 정보 + 3개 해상도 URL + 크기 정보 포함) const [photos] = await pool.query( `SELECT p.id, p.original_url, p.medium_url, p.thumb_url, p.photo_type, p.concept_name, p.sort_order, p.width, p.height, GROUP_CONCAT(m.name ORDER BY m.id SEPARATOR ', ') as members FROM album_photos p LEFT JOIN album_photo_members pm ON p.id = pm.photo_id LEFT JOIN members m ON pm.member_id = m.id WHERE p.album_id = ? GROUP BY p.id ORDER BY p.sort_order`, [album.id] ); // 컨셉별로 그룹화 const conceptPhotos = {}; for (const photo of photos) { const concept = photo.concept_name || "Default"; if (!conceptPhotos[concept]) { conceptPhotos[concept] = []; } conceptPhotos[concept].push({ id: photo.id, original_url: photo.original_url, medium_url: photo.medium_url, thumb_url: photo.thumb_url, width: photo.width, height: photo.height, type: photo.photo_type, members: photo.members, sortOrder: photo.sort_order, }); } album.conceptPhotos = conceptPhotos; return album; } // 전체 앨범 조회 (트랙 포함) router.get("/", async (req, res) => { try { const [albums] = await pool.query( "SELECT id, title, folder_name, album_type, album_type_short, release_date, cover_original_url, cover_medium_url, cover_thumb_url FROM albums ORDER BY release_date DESC" ); // 각 앨범에 트랙 정보 추가 for (const album of albums) { const [tracks] = await pool.query( "SELECT id, track_number, title, is_title_track, duration, lyricist, composer, arranger FROM tracks WHERE album_id = ? ORDER BY track_number", [album.id] ); album.tracks = tracks; } res.json(albums); } catch (error) { console.error("앨범 조회 오류:", error); res.status(500).json({ error: "앨범 정보를 가져오는데 실패했습니다." }); } }); // 앨범명과 트랙명으로 트랙 상세 조회 (더 구체적인 경로이므로 /by-name/:name보다 앞에 배치) router.get("/by-name/:albumName/track/:trackTitle", async (req, res) => { try { const albumName = decodeURIComponent(req.params.albumName); const trackTitle = decodeURIComponent(req.params.trackTitle); // 앨범 조회 const [albums] = await pool.query( "SELECT * FROM albums WHERE folder_name = ? OR title = ?", [albumName, albumName] ); if (albums.length === 0) { return res.status(404).json({ error: "앨범을 찾을 수 없습니다." }); } const album = albums[0]; // 해당 앨범의 트랙 조회 const [tracks] = await pool.query( "SELECT * FROM tracks WHERE album_id = ? AND title = ?", [album.id, trackTitle] ); if (tracks.length === 0) { return res.status(404).json({ error: "트랙을 찾을 수 없습니다." }); } const track = tracks[0]; // 앨범의 다른 트랙 목록 조회 const [otherTracks] = await pool.query( "SELECT id, track_number, title, is_title_track, duration FROM tracks WHERE album_id = ? ORDER BY track_number", [album.id] ); res.json({ ...track, album: { id: album.id, title: album.title, folder_name: album.folder_name, cover_thumb_url: album.cover_thumb_url, cover_medium_url: album.cover_medium_url, release_date: album.release_date, album_type: album.album_type, }, otherTracks, }); } catch (error) { console.error("트랙 조회 오류:", error); res.status(500).json({ error: "트랙 정보를 가져오는데 실패했습니다." }); } }); // 앨범 folder_name 또는 title로 조회 router.get("/by-name/:name", async (req, res) => { try { const name = decodeURIComponent(req.params.name); // folder_name 또는 title로 검색 (PC는 title, 모바일은 folder_name 사용) const [albums] = await pool.query( "SELECT * FROM albums WHERE folder_name = ? OR title = ?", [name, name] ); if (albums.length === 0) { return res.status(404).json({ error: "앨범을 찾을 수 없습니다." }); } const album = await getAlbumDetails(albums[0]); res.json(album); } catch (error) { console.error("앨범 조회 오류:", error); res.status(500).json({ error: "앨범 정보를 가져오는데 실패했습니다." }); } }); // ID로 앨범 조회 router.get("/:id", async (req, res) => { try { const [albums] = await pool.query("SELECT * FROM albums WHERE id = ?", [ req.params.id, ]); if (albums.length === 0) { return res.status(404).json({ error: "앨범을 찾을 수 없습니다." }); } const album = await getAlbumDetails(albums[0]); res.json(album); } catch (error) { console.error("앨범 조회 오류:", error); res.status(500).json({ error: "앨범 정보를 가져오는데 실패했습니다." }); } }); export default router;