Merge pull request '크리에이터 커뮤니티' (#201) from test into main
Reviewed-on: #201
This commit is contained in:
commit
1de705b063
|
@ -17,6 +17,8 @@ data class CreatorCommunity(
|
|||
var isCommentAvailable: Boolean,
|
||||
var isAdult: Boolean,
|
||||
@Column(nullable = true)
|
||||
var audioPath: String? = null,
|
||||
@Column(nullable = true)
|
||||
var imagePath: String? = null,
|
||||
var isActive: Boolean = true
|
||||
) : BaseEntity() {
|
||||
|
@ -26,6 +28,7 @@ data class CreatorCommunity(
|
|||
|
||||
fun toCommunityPostListResponse(
|
||||
imageHost: String,
|
||||
audioUrl: String?,
|
||||
content: String,
|
||||
date: String,
|
||||
isLike: Boolean,
|
||||
|
@ -44,6 +47,7 @@ data class CreatorCommunity(
|
|||
} else {
|
||||
null
|
||||
},
|
||||
audioUrl = audioUrl,
|
||||
content = content,
|
||||
price = price,
|
||||
date = date,
|
||||
|
|
|
@ -27,6 +27,9 @@ class CreatorCommunityController(private val service: CreatorCommunityService) {
|
|||
@PostMapping
|
||||
@PreAuthorize("hasRole('CREATOR')")
|
||||
fun createCommunityPost(
|
||||
@Nullable
|
||||
@RequestPart("audioFile")
|
||||
audioFile: MultipartFile?,
|
||||
@Nullable
|
||||
@RequestPart("postImage")
|
||||
postImage: MultipartFile?,
|
||||
|
@ -37,6 +40,7 @@ class CreatorCommunityController(private val service: CreatorCommunityService) {
|
|||
|
||||
ApiResponse.ok(
|
||||
service.createCommunityPost(
|
||||
audioFile = audioFile,
|
||||
postImage = postImage,
|
||||
requestString = requestString,
|
||||
member = member
|
||||
|
|
|
@ -64,6 +64,7 @@ class CreatorCommunityQueryRepositoryImpl(private val queryFactory: JPAQueryFact
|
|||
creatorCommunity.member.nickname,
|
||||
creatorCommunity.member.profileImage.coalesce("profile/default_profile.png"),
|
||||
creatorCommunity.imagePath,
|
||||
creatorCommunity.audioPath,
|
||||
creatorCommunity.content,
|
||||
creatorCommunity.createdAt,
|
||||
creatorCommunity.isCommentAvailable,
|
||||
|
@ -149,6 +150,7 @@ class CreatorCommunityQueryRepositoryImpl(private val queryFactory: JPAQueryFact
|
|||
creatorCommunity.member.nickname,
|
||||
creatorCommunity.member.profileImage.coalesce("profile/default_profile.png"),
|
||||
creatorCommunity.imagePath,
|
||||
creatorCommunity.audioPath,
|
||||
creatorCommunity.content,
|
||||
creatorCommunity.createdAt,
|
||||
creatorCommunity.isCommentAvailable,
|
||||
|
@ -179,6 +181,7 @@ class CreatorCommunityQueryRepositoryImpl(private val queryFactory: JPAQueryFact
|
|||
creatorCommunity.member.nickname,
|
||||
creatorCommunity.member.profileImage.coalesce("profile/default_profile.png"),
|
||||
creatorCommunity.imagePath,
|
||||
creatorCommunity.audioPath,
|
||||
creatorCommunity.content,
|
||||
creatorCommunity.createdAt,
|
||||
creatorCommunity.isCommentAvailable,
|
||||
|
|
|
@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.explorer.profile.creatorCommunity
|
|||
|
||||
import com.amazonaws.services.s3.model.ObjectMetadata
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import kr.co.vividnext.sodalive.aws.cloudfront.AudioContentCloudFront
|
||||
import kr.co.vividnext.sodalive.aws.s3.S3Uploader
|
||||
import kr.co.vividnext.sodalive.can.payment.CanPaymentService
|
||||
import kr.co.vividnext.sodalive.can.use.CanUsage
|
||||
|
@ -41,22 +42,35 @@ class CreatorCommunityService(
|
|||
|
||||
private val s3Uploader: S3Uploader,
|
||||
private val objectMapper: ObjectMapper,
|
||||
private val audioContentCloudFront: AudioContentCloudFront,
|
||||
private val applicationEventPublisher: ApplicationEventPublisher,
|
||||
|
||||
@Value("\${cloud.aws.s3.bucket}")
|
||||
private val imageBucket: String,
|
||||
|
||||
@Value("\${cloud.aws.s3.content-bucket}")
|
||||
private val contentBucket: String,
|
||||
|
||||
@Value("\${cloud.aws.cloud-front.host}")
|
||||
private val imageHost: String
|
||||
) {
|
||||
@Transactional
|
||||
fun createCommunityPost(postImage: MultipartFile?, requestString: String, member: Member) {
|
||||
fun createCommunityPost(
|
||||
audioFile: MultipartFile?,
|
||||
postImage: MultipartFile?,
|
||||
requestString: String,
|
||||
member: Member
|
||||
) {
|
||||
val request = objectMapper.readValue(requestString, CreateCommunityPostRequest::class.java)
|
||||
|
||||
if (request.price > 0 && postImage == null) {
|
||||
throw SodaException("유료 게시글 등록을 위해서는 이미지가 필요합니다.")
|
||||
}
|
||||
|
||||
if (audioFile != null && postImage == null) {
|
||||
throw SodaException("오디오 등록을 위해서는 이미지가 필요합니다.")
|
||||
}
|
||||
|
||||
val post = CreatorCommunity(
|
||||
content = request.content,
|
||||
price = request.price,
|
||||
|
@ -84,6 +98,20 @@ class CreatorCommunityService(
|
|||
post.imagePath = imagePath
|
||||
}
|
||||
|
||||
if (audioFile != null) {
|
||||
val metadata = ObjectMetadata()
|
||||
metadata.contentLength = audioFile.size
|
||||
|
||||
val audioPath = s3Uploader.upload(
|
||||
inputStream = audioFile.inputStream,
|
||||
bucket = contentBucket,
|
||||
filePath = "creator_community/${post.id}/${generateFileName(prefix = "${post.id}-audio")}.m4a",
|
||||
metadata = metadata
|
||||
)
|
||||
|
||||
post.audioPath = audioPath
|
||||
}
|
||||
|
||||
applicationEventPublisher.publishEvent(
|
||||
FcmEvent(
|
||||
type = FcmEventType.CHANGE_NOTICE,
|
||||
|
@ -186,8 +214,18 @@ class CreatorCommunityService(
|
|||
|
||||
val existOrdered = useCanRepository.isExistOrdered(postId = it.id, memberId = memberId)
|
||||
|
||||
val audioUrl = if ((it.price <= 0 || existOrdered) && it.audioPath != null) {
|
||||
audioContentCloudFront.generateSignedURL(
|
||||
resourcePath = it.audioPath,
|
||||
expirationTime = 1000 * 60 * 30
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
it.toCommunityPostListResponse(
|
||||
imageHost = imageHost,
|
||||
audioUrl = audioUrl,
|
||||
date = getTimeAgoString(it.date),
|
||||
isLike = isLike,
|
||||
memberId = memberId,
|
||||
|
@ -242,8 +280,18 @@ class CreatorCommunityService(
|
|||
|
||||
val existOrdered = useCanRepository.isExistOrdered(postId = post.id, memberId = memberId)
|
||||
|
||||
val audioUrl = if ((post.price <= 0 || existOrdered) && post.audioPath != null) {
|
||||
audioContentCloudFront.generateSignedURL(
|
||||
resourcePath = post.audioPath,
|
||||
expirationTime = 1000 * 60 * 30
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
return post.toCommunityPostListResponse(
|
||||
imageHost = imageHost,
|
||||
audioUrl = audioUrl,
|
||||
date = getTimeAgoString(post.date),
|
||||
isLike = isLike,
|
||||
memberId = memberId,
|
||||
|
@ -414,6 +462,7 @@ class CreatorCommunityService(
|
|||
|
||||
it.toCommunityPostListResponse(
|
||||
imageHost = imageHost,
|
||||
audioUrl = null,
|
||||
date = getTimeAgoString(it.date),
|
||||
isLike = isLike,
|
||||
memberId = memberId,
|
||||
|
@ -480,8 +529,18 @@ class CreatorCommunityService(
|
|||
null
|
||||
}
|
||||
|
||||
val audioUrl = if (post.audioPath != null) {
|
||||
audioContentCloudFront.generateSignedURL(
|
||||
resourcePath = post.audioPath!!,
|
||||
expirationTime = 1000 * 60 * 30
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
return post.toCommunityPostListResponse(
|
||||
imageHost = imageHost,
|
||||
audioUrl = audioUrl,
|
||||
content = post.content,
|
||||
date = getTimeAgoString(post.createdAt!!),
|
||||
isLike = isLike,
|
||||
|
|
|
@ -9,6 +9,7 @@ data class GetCommunityPostListResponse @QueryProjection constructor(
|
|||
val creatorNickname: String,
|
||||
val creatorProfileUrl: String,
|
||||
val imageUrl: String?,
|
||||
val audioUrl: String?,
|
||||
val content: String,
|
||||
val price: Int,
|
||||
val date: String,
|
||||
|
|
|
@ -10,6 +10,7 @@ data class SelectCommunityPostResponse @QueryProjection constructor(
|
|||
val creatorNickname: String,
|
||||
val creatorProfileUrl: String,
|
||||
val imagePath: String?,
|
||||
val audioPath: String?,
|
||||
val content: String,
|
||||
val date: LocalDateTime,
|
||||
val isCommentAvailable: Boolean,
|
||||
|
@ -17,6 +18,7 @@ data class SelectCommunityPostResponse @QueryProjection constructor(
|
|||
) {
|
||||
fun toCommunityPostListResponse(
|
||||
imageHost: String,
|
||||
audioUrl: String?,
|
||||
date: String,
|
||||
isLike: Boolean,
|
||||
memberId: Long,
|
||||
|
@ -35,6 +37,7 @@ data class SelectCommunityPostResponse @QueryProjection constructor(
|
|||
} else {
|
||||
null
|
||||
},
|
||||
audioUrl = audioUrl,
|
||||
content = if (price > 0 && memberId != creatorId) {
|
||||
if (existOrdered) {
|
||||
content
|
||||
|
|
Loading…
Reference in New Issue