From 7cb24449cc9ecd2a26dd503c42e94bb031dd3f03 Mon Sep 17 00:00:00 2001 From: hyungun Date: Thu, 23 Nov 2023 02:10:58 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat=20:=20=ED=94=8C=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * GET /playlists 로 사용자가 가진 플레이리스트 조회 * json 형태로 응답 --- server/src/playlist/playlist.controller.ts | 12 ++++++++++++ server/src/playlist/playlist.service.ts | 14 ++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/server/src/playlist/playlist.controller.ts b/server/src/playlist/playlist.controller.ts index d2220ca..5f176f1 100644 --- a/server/src/playlist/playlist.controller.ts +++ b/server/src/playlist/playlist.controller.ts @@ -1,6 +1,7 @@ import { Body, Controller, + Get, HttpCode, Param, Post, @@ -13,6 +14,7 @@ import { PlaylistService } from './playlist.service'; import { AuthGuard } from '@nestjs/passport'; import { HTTP_STATUS_CODE } from 'src/httpStatusCode.enum'; import { PlaylistCreateDto } from 'src/dto/playlistCreate.dto'; +import { Playlist } from 'src/entity/playlist.entity'; @Controller('playlists') export class PlaylistController { @@ -51,4 +53,14 @@ export class PlaylistController { ); return { music_playlist_id: music_playlist_id }; } + + @Get() + @UseGuards(AuthGuard()) + @HttpCode(HTTP_STATUS_CODE.SUCCESS) + async getUserPlaylists(@Req() req) { + const userId: string = req.user.user_id; + const playlists: Playlist[] = + await this.playlistService.getUserPlaylists(userId); + return playlists; + } } diff --git a/server/src/playlist/playlist.service.ts b/server/src/playlist/playlist.service.ts index b49a0a1..c46c956 100644 --- a/server/src/playlist/playlist.service.ts +++ b/server/src/playlist/playlist.service.ts @@ -82,4 +82,18 @@ export class PlaylistService { return musicCount !== 0; } + + async getUserPlaylists(userId: string): Promise { + const playlists: Playlist[] = await this.playlistRepository.find({ + select: { playlist_Id: true, playlist_title: true }, + where: { + user: { user_id: userId }, + }, + order: { + updated_at: 'ASC', + }, + }); + + return playlists; + } } From 0b65866d7126682a87622b707c70f6e7ef36f66e Mon Sep 17 00:00:00 2001 From: hyungun Date: Thu, 23 Nov 2023 02:28:39 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat=20:=20=ED=94=8C=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=9D=8C=EC=95=85=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 음악을 추가했을 때 플레이리스트의 update_at 필드를 갱신하도록 구현 --- server/src/playlist/playlist.service.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/server/src/playlist/playlist.service.ts b/server/src/playlist/playlist.service.ts index c46c956..e1b4421 100644 --- a/server/src/playlist/playlist.service.ts +++ b/server/src/playlist/playlist.service.ts @@ -61,6 +61,7 @@ export class PlaylistService { const result: Music_Playlist = await this.music_playlistRepository.save(new_music_playlist); + this.setUpdatedAtNow(playlistId); return result.music_playlist_id; } @@ -83,6 +84,14 @@ export class PlaylistService { return musicCount !== 0; } + async setUpdatedAtNow(playlistId: number): Promise { + const targetPlaylist: Playlist = await this.playlistRepository.findOne({ + where: { playlist_Id: playlistId }, + }); + targetPlaylist.updated_at = new Date(); + this.playlistRepository.save(targetPlaylist); + } + async getUserPlaylists(userId: string): Promise { const playlists: Playlist[] = await this.playlistRepository.find({ select: { playlist_Id: true, playlist_title: true }, From 5c0a5f69445a55a38bf741848d2aeffc982a4fb4 Mon Sep 17 00:00:00 2001 From: hyungun Date: Thu, 23 Nov 2023 02:50:03 +0900 Subject: [PATCH 3/6] =?UTF-8?q?refactor=20:=20=EC=9D=8C=EC=95=85=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20API=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 플레이리스트에 이미 추가된 음악이라면 400 응답 --- server/src/playlist/playlist.service.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/server/src/playlist/playlist.service.ts b/server/src/playlist/playlist.service.ts index e1b4421..8101c75 100644 --- a/server/src/playlist/playlist.service.ts +++ b/server/src/playlist/playlist.service.ts @@ -52,6 +52,11 @@ export class PlaylistService { throw new HttpException('NOT_EXIST_MUSIC', HTTP_STATUS_CODE.BAD_REQUEST); } + // 이미 추가된 음악인지 확인 + if (await this.isAlreadyAdded(playlistId, musicId)) { + throw new HttpException('ALREADY_ADDED', HTTP_STATUS_CODE.BAD_REQUEST); + } + // 관계테이블에 추가 const new_music_playlist: Music_Playlist = this.music_playlistRepository.create({ @@ -65,6 +70,14 @@ export class PlaylistService { return result.music_playlist_id; } + async isAlreadyAdded(playlistId: number, musicId: number): Promise { + const count: number = await this.music_playlistRepository.countBy({ + music: { musicId: musicId }, + playlist: { playlist_Id: playlistId }, + }); + return count !== 0; + } + async isExistPlaylistOnUser( playlistId: number, userId: string, From c176318f8888a86bf45302f76e2f8973b00dc42a Mon Sep 17 00:00:00 2001 From: hyungun Date: Thu, 23 Nov 2023 04:18:39 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat=20:=20=ED=94=8C=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=9D=8C=EC=95=85=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 플레이리스트에 있는 음악들의 정보를 응답 --- server/src/playlist/playlist.controller.ts | 14 +++++++- server/src/playlist/playlist.service.ts | 41 +++++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/server/src/playlist/playlist.controller.ts b/server/src/playlist/playlist.controller.ts index 5f176f1..e2e28eb 100644 --- a/server/src/playlist/playlist.controller.ts +++ b/server/src/playlist/playlist.controller.ts @@ -15,6 +15,7 @@ import { AuthGuard } from '@nestjs/passport'; import { HTTP_STATUS_CODE } from 'src/httpStatusCode.enum'; import { PlaylistCreateDto } from 'src/dto/playlistCreate.dto'; import { Playlist } from 'src/entity/playlist.entity'; +import { Music } from 'src/entity/music.entity'; @Controller('playlists') export class PlaylistController { @@ -57,10 +58,21 @@ export class PlaylistController { @Get() @UseGuards(AuthGuard()) @HttpCode(HTTP_STATUS_CODE.SUCCESS) - async getUserPlaylists(@Req() req) { + async getUserPlaylists(@Req() req): Promise { const userId: string = req.user.user_id; const playlists: Playlist[] = await this.playlistService.getUserPlaylists(userId); return playlists; } + + @Get(':playlistId') + @UseGuards(AuthGuard()) + @HttpCode(HTTP_STATUS_CODE.SUCCESS) + async getPlaylistMusics( + @Req() req, + @Param('playlistId') playlistId: number, + ): Promise { + const userId: string = req.user.user_id; + return await this.playlistService.getPlaylistMusics(userId, playlistId); + } } diff --git a/server/src/playlist/playlist.service.ts b/server/src/playlist/playlist.service.ts index 8101c75..379bd54 100644 --- a/server/src/playlist/playlist.service.ts +++ b/server/src/playlist/playlist.service.ts @@ -112,10 +112,49 @@ export class PlaylistService { user: { user_id: userId }, }, order: { - updated_at: 'ASC', + updated_at: 'DESC', }, }); return playlists; } + + async getPlaylistMusics( + userId: string, + playlistId: number, + ): Promise { + if (!(await this.isExistPlaylistOnUser(playlistId, userId))) { + throw new HttpException( + 'NOT_EXIST_PLAYLIST_ON_USER', + HTTP_STATUS_CODE.BAD_REQUEST, + ); + } + + const musics: Music[] = await this.music_playlistRepository + .find({ + relations: { + music: { user: true }, + }, + where: { + playlist: { playlist_Id: playlistId }, + }, + select: { + music: { + musicId: true, + title: true, + cover: true, + musicFile: true, + genre: true, + user: { user_id: true, nickname: true }, + }, + music_playlist_id: false, + }, + order: { + music_playlist_id: 'DESC', + }, + }) + .then((a: Music_Playlist[]) => a.map((b) => b.music)); + + return musics; + } } From d21ce84def630129fa7b3e8440295e424fffe333 Mon Sep 17 00:00:00 2001 From: hyungun Date: Thu, 23 Nov 2023 04:34:20 +0900 Subject: [PATCH 5/6] =?UTF-8?q?refactor=20:=20Active=20Record=20=ED=8C=A8?= =?UTF-8?q?=ED=84=B4=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 긴 로직에 대해서 Active Record 패턴 적용 * service 에서 가독성 증가 --- server/src/entity/music_playlist.entity.ts | 41 +++++++++++++++++++--- server/src/entity/playlist.entity.ts | 12 +++++++ server/src/playlist/playlist.service.ts | 40 ++------------------- 3 files changed, 50 insertions(+), 43 deletions(-) diff --git a/server/src/entity/music_playlist.entity.ts b/server/src/entity/music_playlist.entity.ts index a323aec..b61f019 100644 --- a/server/src/entity/music_playlist.entity.ts +++ b/server/src/entity/music_playlist.entity.ts @@ -1,4 +1,10 @@ -import { BaseEntity, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; +import { + BaseEntity, + Entity, + JoinColumn, + ManyToOne, + PrimaryGeneratedColumn, +} from 'typeorm'; import { Music } from './music.entity'; import { Playlist } from './playlist.entity'; @@ -8,10 +14,35 @@ export class Music_Playlist extends BaseEntity { music_playlist_id: number; @ManyToOne(() => Music, (music) => music.music_playlist) - @JoinColumn({name: 'music_id'}) - music: Music + @JoinColumn({ name: 'music_id' }) + music: Music; @ManyToOne(() => Playlist, (playlist) => playlist.music_playlist) - @JoinColumn({name: 'playlist_id'}) - playlist: Playlist + @JoinColumn({ name: 'playlist_id' }) + playlist: Playlist; + + static async getMusicListByPlaylistId(playlistId: number): Promise { + return this.find({ + relations: { + music: { user: true }, + }, + where: { + playlist: { playlist_Id: playlistId }, + }, + select: { + music: { + musicId: true, + title: true, + cover: true, + musicFile: true, + genre: true, + user: { user_id: true, nickname: true }, + }, + music_playlist_id: false, + }, + order: { + music_playlist_id: 'DESC', + }, + }).then((a: Music_Playlist[]) => a.map((b) => b.music)); + } } diff --git a/server/src/entity/playlist.entity.ts b/server/src/entity/playlist.entity.ts index aabc850..d5d9391 100644 --- a/server/src/entity/playlist.entity.ts +++ b/server/src/entity/playlist.entity.ts @@ -31,4 +31,16 @@ export class Playlist extends BaseEntity { @OneToMany(() => Music_Playlist, (music_playlist) => music_playlist.playlist) music_playlist: Music_Playlist[]; + + static async getPlaylistsByUserId(userId: string): Promise { + return this.find({ + select: { playlist_Id: true, playlist_title: true }, + where: { + user: { user_id: userId }, + }, + order: { + updated_at: 'DESC', + }, + }); + } } diff --git a/server/src/playlist/playlist.service.ts b/server/src/playlist/playlist.service.ts index 379bd54..680cf99 100644 --- a/server/src/playlist/playlist.service.ts +++ b/server/src/playlist/playlist.service.ts @@ -106,17 +106,7 @@ export class PlaylistService { } async getUserPlaylists(userId: string): Promise { - const playlists: Playlist[] = await this.playlistRepository.find({ - select: { playlist_Id: true, playlist_title: true }, - where: { - user: { user_id: userId }, - }, - order: { - updated_at: 'DESC', - }, - }); - - return playlists; + return Playlist.getPlaylistsByUserId(userId); } async getPlaylistMusics( @@ -129,32 +119,6 @@ export class PlaylistService { HTTP_STATUS_CODE.BAD_REQUEST, ); } - - const musics: Music[] = await this.music_playlistRepository - .find({ - relations: { - music: { user: true }, - }, - where: { - playlist: { playlist_Id: playlistId }, - }, - select: { - music: { - musicId: true, - title: true, - cover: true, - musicFile: true, - genre: true, - user: { user_id: true, nickname: true }, - }, - music_playlist_id: false, - }, - order: { - music_playlist_id: 'DESC', - }, - }) - .then((a: Music_Playlist[]) => a.map((b) => b.music)); - - return musics; + return Music_Playlist.getMusicListByPlaylistId(playlistId); } } From d2deb7134336c74bd8f7a2b3377617bc047002dd Mon Sep 17 00:00:00 2001 From: hyungun Date: Thu, 23 Nov 2023 10:46:38 +0900 Subject: [PATCH 6/6] =?UTF-8?q?refactor=20:=20playlist.service=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 서버 DB 조회 에러 처리 추가 --- server/src/playlist/playlist.service.ts | 112 +++++++++++++++--------- 1 file changed, 72 insertions(+), 40 deletions(-) diff --git a/server/src/playlist/playlist.service.ts b/server/src/playlist/playlist.service.ts index 680cf99..54f77a9 100644 --- a/server/src/playlist/playlist.service.ts +++ b/server/src/playlist/playlist.service.ts @@ -22,17 +22,21 @@ export class PlaylistService { userId: string, playlistCreateDto: PlaylistCreateDto, ): Promise { - const title: string = playlistCreateDto.title; - const newPlaylist: Playlist = this.playlistRepository.create({ - playlist_title: title, - created_at: new Date(), - updated_at: new Date(), - user: { user_id: userId }, - }); + try { + const title: string = playlistCreateDto.title; + const newPlaylist: Playlist = this.playlistRepository.create({ + playlist_title: title, + created_at: new Date(), + updated_at: new Date(), + user: { user_id: userId }, + }); - const result: Playlist = await this.playlistRepository.save(newPlaylist); - const playlistId: number = result.playlist_Id; - return playlistId; + const result: Playlist = await this.playlistRepository.save(newPlaylist); + const playlistId: number = result.playlist_Id; + return playlistId; + } catch { + throw new HttpException('SERVER_ERROR', HTTP_STATUS_CODE.SERVER_ERROR); + } } async addMusicToPlaylist( @@ -58,55 +62,79 @@ export class PlaylistService { } // 관계테이블에 추가 - const new_music_playlist: Music_Playlist = - this.music_playlistRepository.create({ - music: { musicId: musicId }, - playlist: { playlist_Id: playlistId }, - }); + try { + const new_music_playlist: Music_Playlist = + this.music_playlistRepository.create({ + music: { musicId: musicId }, + playlist: { playlist_Id: playlistId }, + }); - const result: Music_Playlist = - await this.music_playlistRepository.save(new_music_playlist); - this.setUpdatedAtNow(playlistId); - return result.music_playlist_id; + const result: Music_Playlist = + await this.music_playlistRepository.save(new_music_playlist); + this.setUpdatedAtNow(playlistId); + return result.music_playlist_id; + } catch { + throw new HttpException('SERVER_ERROR', HTTP_STATUS_CODE.SERVER_ERROR); + } } async isAlreadyAdded(playlistId: number, musicId: number): Promise { - const count: number = await this.music_playlistRepository.countBy({ - music: { musicId: musicId }, - playlist: { playlist_Id: playlistId }, - }); - return count !== 0; + try { + const count: number = await this.music_playlistRepository.countBy({ + music: { musicId: musicId }, + playlist: { playlist_Id: playlistId }, + }); + return count !== 0; + } catch { + throw new HttpException('SERVER_ERROR', HTTP_STATUS_CODE.SERVER_ERROR); + } } async isExistPlaylistOnUser( playlistId: number, userId: string, ): Promise { - const playlistCount: number = await this.playlistRepository.countBy({ - playlist_Id: playlistId, - user: { user_id: userId }, - }); - return playlistCount !== 0; + try { + const playlistCount: number = await this.playlistRepository.countBy({ + playlist_Id: playlistId, + user: { user_id: userId }, + }); + return playlistCount !== 0; + } catch { + throw new HttpException('SERVER_ERROR', HTTP_STATUS_CODE.SERVER_ERROR); + } } async isExistMusic(musicId: number): Promise { - const musicCount: number = await this.MusicRepository.countBy({ - musicId: musicId, - }); + try { + const musicCount: number = await this.MusicRepository.countBy({ + musicId: musicId, + }); - return musicCount !== 0; + return musicCount !== 0; + } catch { + throw new HttpException('SERVER_ERROR', HTTP_STATUS_CODE.SERVER_ERROR); + } } async setUpdatedAtNow(playlistId: number): Promise { - const targetPlaylist: Playlist = await this.playlistRepository.findOne({ - where: { playlist_Id: playlistId }, - }); - targetPlaylist.updated_at = new Date(); - this.playlistRepository.save(targetPlaylist); + try { + const targetPlaylist: Playlist = await this.playlistRepository.findOne({ + where: { playlist_Id: playlistId }, + }); + targetPlaylist.updated_at = new Date(); + this.playlistRepository.save(targetPlaylist); + } catch { + throw new HttpException('SERVER_ERROR', HTTP_STATUS_CODE.SERVER_ERROR); + } } async getUserPlaylists(userId: string): Promise { - return Playlist.getPlaylistsByUserId(userId); + try { + return Playlist.getPlaylistsByUserId(userId); + } catch { + throw new HttpException('SERVER_ERROR', HTTP_STATUS_CODE.SERVER_ERROR); + } } async getPlaylistMusics( @@ -119,6 +147,10 @@ export class PlaylistService { HTTP_STATUS_CODE.BAD_REQUEST, ); } - return Music_Playlist.getMusicListByPlaylistId(playlistId); + try { + return Music_Playlist.getMusicListByPlaylistId(playlistId); + } catch { + throw new HttpException('SERVER_ERROR', HTTP_STATUS_CODE.SERVER_ERROR); + } } }