Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

노래 삭제 API 구현 #370

Merged
merged 4 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions server/src/entity/music.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,22 @@ export class Music extends BaseEntity {
},
});
}

static async isExistMusicId(musicId: string): Promise<boolean> {
const count: number = await this.count({ where: { music_id: musicId } });
if (count === 0) {
return false;
}
return true;
}

static async isMusicOwner(musicId: string, userId: string): Promise<boolean> {
const count: number = await this.count({
where: { music_id: musicId, user: { user_id: userId } },
});
if (count === 0) {
return false;
}
return true;
}
}
4 changes: 3 additions & 1 deletion server/src/entity/music_playlist.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ export class Music_Playlist extends BaseEntity {
@PrimaryGeneratedColumn()
music_playlist_id: number;

@ManyToOne(() => Music, (music) => music.music_playlist)
@ManyToOne(() => Music, (music) => music.music_playlist, {
onDelete: 'CASCADE',
})
Comment on lines +18 to +20
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

엔티티에서 옵션을 걸어 삭제하는 방식은 제가 고려하지 않았던 것 같은데 훨씬 효율적일 것 같아요 제 코드도 리팩토링 해봐야겠네요 ! 👍

@JoinColumn({ name: 'music_id' })
music: Music;

Expand Down
4 changes: 3 additions & 1 deletion server/src/entity/recent_played.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ export class Recent_Played extends BaseEntity {
@PrimaryGeneratedColumn()
recent_played_id: number;

@ManyToOne(() => Music, (music) => music.recent_played)
@ManyToOne(() => Music, (music) => music.recent_played, {
onDelete: 'CASCADE',
})
@JoinColumn({ name: 'music_id' })
music: Music;

Expand Down
16 changes: 13 additions & 3 deletions server/src/music/music.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
ValidationPipe,
Query,
Logger,
Delete,
} from '@nestjs/common';
import { MusicService } from './music.service';
import { HTTP_STATUS_CODE } from 'src/httpStatusCode.enum';
Expand All @@ -22,9 +23,7 @@ import { Music } from 'src/entity/music.entity';
export class MusicController {
private readonly logger = new Logger('Music');
private objectStorage: AWS.S3;
constructor(
private readonly musicService: MusicService,
) {}
constructor(private readonly musicService: MusicService) {}

@Post()
@UsePipes(ValidationPipe)
Expand Down Expand Up @@ -103,4 +102,15 @@ export class MusicController {
this.logger.log(`GET /musics/search - keyword=${keyword}`);
return this.musicService.getCertainKeywordNicknameUser(keyword);
}

@Delete()
@UseGuards(AuthGuard())
@HttpCode(HTTP_STATUS_CODE.SUCCESS)
async deleteMusic(
@Req() req,
@Body('music_id') music_id: string,
): Promise<string> {
const userId = req.user.user_id;
return await this.musicService.deleteMusicById(music_id, userId);
}
}
86 changes: 86 additions & 0 deletions server/src/music/music.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ERROR_CODE } from 'src/config/errorCode.enum';
import { UploadService } from 'src/upload/upload.service';
import { NcloudConfigService } from 'src/config/ncloud.config';
import { AWSError } from 'aws-sdk';
import { DeleteObjectOutput } from 'aws-sdk/clients/s3';

@Injectable()
export class MusicService {
Expand Down Expand Up @@ -187,4 +188,89 @@ export class MusicService {
);
}
}

async deleteMusicById(musicId: string, userId: string): Promise<string> {
if (!(await Music.isMusicOwner(musicId, userId))) {
this.logger.error(`music.service - deleteMusicById : NOT_EXIST_MUSIC`);
throw new CatchyException(
'NOT_EXIST_MUSIC',
HTTP_STATUS_CODE.SERVER_ERROR,
ERROR_CODE.NOT_EXIST_MUSIC,
);
}

try {
const music: Music = await Music.getMusicById(musicId);
this.musicRepository.delete(music.music_id);

const sliceCount: number =
'https://catchy-tape-bucket2.kr.object.ncloudstorage.com/'.length;
const musicFilePath: string = music.music_file.slice(sliceCount, sliceCount + 41);
const coverFilePath: string = music.cover.slice(sliceCount, sliceCount + 46);
console.log(coverFilePath, musicFilePath);
Copy link
Member

@sk000801 sk000801 Jan 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

위의 저 path 변수 두 개는 이후 경로의 /uuid/image.png 이 문자열 값까지 계산하신 건가요 !?
상수로 빼도 괜찮을 것 같아요 ! (중요하진 않습니당)

아니면 slice 대신 https://~.com/ 요 부분을 replace 시키는 건 어떻게 생각하시나요 !?

그리구 console.log 빼주셔도 될 것 같아요!!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

상수로 빼서 처리하겠습니다!


if (musicFilePath) this.deleteFolder(musicFilePath);
if (coverFilePath) this.deleteFolder(coverFilePath);

return music.music_id;
} catch {
this.logger.error(`music.service - deleteMusicById : SERVICE_ERROR`);
throw new CatchyException(
'SERVICE_ERROR',
HTTP_STATUS_CODE.SERVER_ERROR,
ERROR_CODE.SERVICE_ERROR,
);
}
}

async deleteFolder(folderPath) {
let params = {
Bucket: 'catchy-tape-bucket2',
Delete: {
Objects: [],
},
};

// 폴더 내의 파일들을 삭제할 객체 목록에 추가
const filesInFolder = await this.listFilesInFolder(folderPath);
filesInFolder.forEach((file) => {
params.Delete.Objects.push({ Key: file.Key });
});

try {
// 폴더 내의 파일들을 삭제
await this.objectStorage.deleteObjects(params).promise();

// 폴더를 삭제
await this.objectStorage
.deleteObject({ Bucket: 'catchy-tape-bucket2', Key: folderPath })
.promise();
} catch (error) {
this.logger.error(`music.service - deleteFolder : SERVICE_ERROR`);
throw new CatchyException(
'SERVICE_ERROR',
HTTP_STATUS_CODE.SERVER_ERROR,
ERROR_CODE.SERVICE_ERROR,
);
}
}

async listFilesInFolder(folderPath) {
let params = {
Bucket: 'catchy-tape-bucket2',
Prefix: folderPath,
};

try {
const data = await this.objectStorage.listObjectsV2(params).promise();
return data.Contents;
} catch (error) {
this.logger.error(`music.service - listFilesInFolder : SERVICE_ERROR`);
throw new CatchyException(
'SERVICE_ERROR',
HTTP_STATUS_CODE.SERVER_ERROR,
ERROR_CODE.SERVICE_ERROR,
);
}
}
}
Loading