Merge pull request '예약 업로드' (#113) from test into main
Reviewed-on: #113
This commit is contained in:
commit
b82fdfb2c8
|
@ -5,6 +5,7 @@ import kr.co.vividnext.sodalive.content.hashtag.AudioContentHashTag
|
||||||
import kr.co.vividnext.sodalive.content.main.curation.AudioContentCuration
|
import kr.co.vividnext.sodalive.content.main.curation.AudioContentCuration
|
||||||
import kr.co.vividnext.sodalive.content.theme.AudioContentTheme
|
import kr.co.vividnext.sodalive.content.theme.AudioContentTheme
|
||||||
import kr.co.vividnext.sodalive.member.Member
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
|
import java.time.LocalDateTime
|
||||||
import javax.persistence.CascadeType
|
import javax.persistence.CascadeType
|
||||||
import javax.persistence.Column
|
import javax.persistence.Column
|
||||||
import javax.persistence.Entity
|
import javax.persistence.Entity
|
||||||
|
@ -32,6 +33,7 @@ data class AudioContent(
|
||||||
@Column(columnDefinition = "TEXT", nullable = false)
|
@Column(columnDefinition = "TEXT", nullable = false)
|
||||||
var detail: String,
|
var detail: String,
|
||||||
val price: Int = 0,
|
val price: Int = 0,
|
||||||
|
var releaseDate: LocalDateTime? = null,
|
||||||
@Enumerated(value = EnumType.STRING)
|
@Enumerated(value = EnumType.STRING)
|
||||||
val type: AudioContentType = AudioContentType.INDIVIDUAL,
|
val type: AudioContentType = AudioContentType.INDIVIDUAL,
|
||||||
val isGeneratePreview: Boolean = true,
|
val isGeneratePreview: Boolean = true,
|
||||||
|
|
|
@ -25,7 +25,10 @@ import java.time.temporal.TemporalAdjusters
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/audio-content")
|
@RequestMapping("/audio-content")
|
||||||
class AudioContentController(private val service: AudioContentService) {
|
class AudioContentController(
|
||||||
|
private val service: AudioContentService,
|
||||||
|
private val repository: AudioContentRepository
|
||||||
|
) {
|
||||||
@PostMapping
|
@PostMapping
|
||||||
@PreAuthorize("hasRole('CREATOR')")
|
@PreAuthorize("hasRole('CREATOR')")
|
||||||
fun createAudioContent(
|
fun createAudioContent(
|
||||||
|
@ -190,4 +193,16 @@ class AudioContentController(private val service: AudioContentService) {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/release")
|
||||||
|
@PreAuthorize("hasRole('BOT')")
|
||||||
|
fun releaseContent() = run {
|
||||||
|
val contentIdList = repository.getNotReleaseContentId()
|
||||||
|
|
||||||
|
for (contentId in contentIdList) {
|
||||||
|
service.releaseContent(contentId)
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiResponse.ok(null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ interface AudioContentQueryRepository {
|
||||||
|
|
||||||
fun findByTheme(
|
fun findByTheme(
|
||||||
cloudfrontHost: String,
|
cloudfrontHost: String,
|
||||||
|
memberId: Long,
|
||||||
theme: String = "",
|
theme: String = "",
|
||||||
isAdult: Boolean = false,
|
isAdult: Boolean = false,
|
||||||
offset: Long = 0,
|
offset: Long = 0,
|
||||||
|
@ -64,13 +65,14 @@ interface AudioContentQueryRepository {
|
||||||
|
|
||||||
fun findByThemeFor2Weeks(
|
fun findByThemeFor2Weeks(
|
||||||
cloudfrontHost: String,
|
cloudfrontHost: String,
|
||||||
|
memberId: Long,
|
||||||
theme: String = "",
|
theme: String = "",
|
||||||
isAdult: Boolean = false,
|
isAdult: Boolean = false,
|
||||||
offset: Long = 0,
|
offset: Long = 0,
|
||||||
limit: Long = 20
|
limit: Long = 20
|
||||||
): List<GetAudioContentMainItem>
|
): List<GetAudioContentMainItem>
|
||||||
|
|
||||||
fun totalCountNewContentFor2Weeks(theme: String, isAdult: Boolean): Int
|
fun totalCountNewContentFor2Weeks(theme: String, memberId: Long, isAdult: Boolean): Int
|
||||||
|
|
||||||
fun getNewContentUploadCreatorList(
|
fun getNewContentUploadCreatorList(
|
||||||
cloudfrontHost: String,
|
cloudfrontHost: String,
|
||||||
|
@ -96,6 +98,8 @@ interface AudioContentQueryRepository {
|
||||||
): List<GetAudioContentRankingItem>
|
): List<GetAudioContentRankingItem>
|
||||||
|
|
||||||
fun getAudioContentCurationList(isAdult: Boolean, offset: Long, limit: Long): List<AudioContentCuration>
|
fun getAudioContentCurationList(isAdult: Boolean, offset: Long, limit: Long): List<AudioContentCuration>
|
||||||
|
|
||||||
|
fun getNotReleaseContentId(): List<Long>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
|
@ -146,8 +150,11 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
|
||||||
SortType.PRICE_LOW -> audioContent.price.asc()
|
SortType.PRICE_LOW -> audioContent.price.asc()
|
||||||
}
|
}
|
||||||
|
|
||||||
var where = audioContent.isActive.isTrue
|
var where = audioContent.member.id.eq(creatorId)
|
||||||
.and(audioContent.member.id.eq(creatorId))
|
.and(
|
||||||
|
audioContent.isActive.isTrue
|
||||||
|
.or(audioContent.releaseDate.isNotNull.and(audioContent.duration.isNotNull))
|
||||||
|
)
|
||||||
|
|
||||||
if (!isAdult) {
|
if (!isAdult) {
|
||||||
where = where.and(audioContent.isAdult.isFalse)
|
where = where.and(audioContent.isAdult.isFalse)
|
||||||
|
@ -166,8 +173,11 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
|
||||||
creatorId: Long,
|
creatorId: Long,
|
||||||
isAdult: Boolean
|
isAdult: Boolean
|
||||||
): Int {
|
): Int {
|
||||||
var where = audioContent.isActive.isTrue
|
var where = audioContent.member.id.eq(creatorId)
|
||||||
.and(audioContent.member.id.eq(creatorId))
|
.and(
|
||||||
|
audioContent.isActive.isTrue
|
||||||
|
.or(audioContent.releaseDate.isNotNull.and(audioContent.duration.isNotNull))
|
||||||
|
)
|
||||||
|
|
||||||
if (!isAdult) {
|
if (!isAdult) {
|
||||||
where = where.and(audioContent.isAdult.isFalse)
|
where = where.and(audioContent.isAdult.isFalse)
|
||||||
|
@ -242,12 +252,18 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
|
||||||
|
|
||||||
override fun findByTheme(
|
override fun findByTheme(
|
||||||
cloudfrontHost: String,
|
cloudfrontHost: String,
|
||||||
|
memberId: Long,
|
||||||
theme: String,
|
theme: String,
|
||||||
isAdult: Boolean,
|
isAdult: Boolean,
|
||||||
offset: Long,
|
offset: Long,
|
||||||
limit: Long
|
limit: Long
|
||||||
): List<GetAudioContentMainItem> {
|
): List<GetAudioContentMainItem> {
|
||||||
var where = audioContent.isActive.isTrue
|
var where = audioContent.isActive.isTrue
|
||||||
|
.and(
|
||||||
|
audioContent.releaseDate.isNull
|
||||||
|
.or(audioContent.releaseDate.loe(LocalDateTime.now()))
|
||||||
|
.or(audioContent.member.id.eq(memberId))
|
||||||
|
)
|
||||||
|
|
||||||
if (!isAdult) {
|
if (!isAdult) {
|
||||||
where = where.and(audioContent.isAdult.isFalse)
|
where = where.and(audioContent.isAdult.isFalse)
|
||||||
|
@ -278,9 +294,14 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
|
||||||
.fetch()
|
.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun totalCountNewContentFor2Weeks(theme: String, isAdult: Boolean): Int {
|
override fun totalCountNewContentFor2Weeks(theme: String, memberId: Long, isAdult: Boolean): Int {
|
||||||
var where = audioContent.isActive.isTrue
|
var where = audioContent.isActive.isTrue
|
||||||
.and(audioContent.createdAt.goe(LocalDateTime.now().minusWeeks(2)))
|
.and(audioContent.createdAt.goe(LocalDateTime.now().minusWeeks(2)))
|
||||||
|
.and(
|
||||||
|
audioContent.releaseDate.isNull
|
||||||
|
.or(audioContent.releaseDate.loe(LocalDateTime.now()))
|
||||||
|
.or(audioContent.member.id.eq(memberId))
|
||||||
|
)
|
||||||
|
|
||||||
if (!isAdult) {
|
if (!isAdult) {
|
||||||
where = where.and(audioContent.isAdult.isFalse)
|
where = where.and(audioContent.isAdult.isFalse)
|
||||||
|
@ -302,6 +323,7 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
|
||||||
|
|
||||||
override fun findByThemeFor2Weeks(
|
override fun findByThemeFor2Weeks(
|
||||||
cloudfrontHost: String,
|
cloudfrontHost: String,
|
||||||
|
memberId: Long,
|
||||||
theme: String,
|
theme: String,
|
||||||
isAdult: Boolean,
|
isAdult: Boolean,
|
||||||
offset: Long,
|
offset: Long,
|
||||||
|
@ -309,6 +331,11 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
|
||||||
): List<GetAudioContentMainItem> {
|
): List<GetAudioContentMainItem> {
|
||||||
var where = audioContent.isActive.isTrue
|
var where = audioContent.isActive.isTrue
|
||||||
.and(audioContent.createdAt.goe(LocalDateTime.now().minusWeeks(2)))
|
.and(audioContent.createdAt.goe(LocalDateTime.now().minusWeeks(2)))
|
||||||
|
.and(
|
||||||
|
audioContent.releaseDate.isNull
|
||||||
|
.or(audioContent.releaseDate.loe(LocalDateTime.now()))
|
||||||
|
.or(audioContent.member.id.eq(memberId))
|
||||||
|
)
|
||||||
|
|
||||||
if (!isAdult) {
|
if (!isAdult) {
|
||||||
where = where.and(audioContent.isAdult.isFalse)
|
where = where.and(audioContent.isAdult.isFalse)
|
||||||
|
@ -562,4 +589,16 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
|
||||||
.orderBy(audioContentCuration.orders.asc())
|
.orderBy(audioContentCuration.orders.asc())
|
||||||
.fetch()
|
.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getNotReleaseContentId(): List<Long> {
|
||||||
|
val where = audioContent.isActive.isFalse
|
||||||
|
.and(audioContent.releaseDate.isNotNull)
|
||||||
|
.and(audioContent.releaseDate.loe(LocalDateTime.now()))
|
||||||
|
|
||||||
|
return queryFactory
|
||||||
|
.select(audioContent.id)
|
||||||
|
.from(audioContent)
|
||||||
|
.where(where)
|
||||||
|
.fetch()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import kr.co.vividnext.sodalive.content.order.OrderRepository
|
||||||
import kr.co.vividnext.sodalive.content.order.OrderType
|
import kr.co.vividnext.sodalive.content.order.OrderType
|
||||||
import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository
|
import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository
|
||||||
import kr.co.vividnext.sodalive.explorer.ExplorerQueryRepository
|
import kr.co.vividnext.sodalive.explorer.ExplorerQueryRepository
|
||||||
|
import kr.co.vividnext.sodalive.extensions.convertLocalDateTime
|
||||||
import kr.co.vividnext.sodalive.fcm.FcmEvent
|
import kr.co.vividnext.sodalive.fcm.FcmEvent
|
||||||
import kr.co.vividnext.sodalive.fcm.FcmEventType
|
import kr.co.vividnext.sodalive.fcm.FcmEventType
|
||||||
import kr.co.vividnext.sodalive.member.Member
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
|
@ -125,6 +126,7 @@ class AudioContentService(
|
||||||
?: throw SodaException("잘못된 콘텐츠 입니다.\n다시 시도해 주세요.")
|
?: throw SodaException("잘못된 콘텐츠 입니다.\n다시 시도해 주세요.")
|
||||||
|
|
||||||
audioContent.isActive = false
|
audioContent.isActive = false
|
||||||
|
audioContent.releaseDate = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@ -143,6 +145,15 @@ class AudioContentService(
|
||||||
// 미리듣기 시간 체크
|
// 미리듣기 시간 체크
|
||||||
validatePreviewTime(request.previewStartTime, request.previewEndTime)
|
validatePreviewTime(request.previewStartTime, request.previewEndTime)
|
||||||
|
|
||||||
|
val releaseDate = if (request.releaseDate != null) {
|
||||||
|
request.releaseDate.convertLocalDateTime("yyyy-MM-dd HH:mm")
|
||||||
|
.atZone(ZoneId.of(request.timezone))
|
||||||
|
.withZoneSameInstant(ZoneId.of("UTC"))
|
||||||
|
.toLocalDateTime()
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
// contentFile 체크
|
// contentFile 체크
|
||||||
if (contentFile == null && request.type == AudioContentType.INDIVIDUAL) {
|
if (contentFile == null && request.type == AudioContentType.INDIVIDUAL) {
|
||||||
throw SodaException("콘텐츠를 선택해 주세요.")
|
throw SodaException("콘텐츠를 선택해 주세요.")
|
||||||
|
@ -168,6 +179,7 @@ class AudioContentService(
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
},
|
},
|
||||||
|
releaseDate = releaseDate,
|
||||||
isAdult = request.isAdult,
|
isAdult = request.isAdult,
|
||||||
isGeneratePreview = if (request.type == AudioContentType.INDIVIDUAL) {
|
isGeneratePreview = if (request.type == AudioContentType.INDIVIDUAL) {
|
||||||
request.isGeneratePreview
|
request.isGeneratePreview
|
||||||
|
@ -331,7 +343,6 @@ class AudioContentService(
|
||||||
val audioContent = repository.findByIdOrNull(contentId)
|
val audioContent = repository.findByIdOrNull(contentId)
|
||||||
?: throw SodaException("잘못된 요청입니다.")
|
?: throw SodaException("잘못된 요청입니다.")
|
||||||
|
|
||||||
audioContent.isActive = true
|
|
||||||
audioContent.content = content
|
audioContent.content = content
|
||||||
audioContent.duration = duration
|
audioContent.duration = duration
|
||||||
|
|
||||||
|
@ -346,6 +357,42 @@ class AudioContentService(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (audioContent.releaseDate == null) {
|
||||||
|
audioContent.isActive = true
|
||||||
|
|
||||||
|
applicationEventPublisher.publishEvent(
|
||||||
|
FcmEvent(
|
||||||
|
type = FcmEventType.UPLOAD_CONTENT,
|
||||||
|
title = audioContent.member!!.nickname,
|
||||||
|
message = "콘텐츠를 업로드 하였습니다. - ${audioContent.title}",
|
||||||
|
isAuth = audioContent.isAdult,
|
||||||
|
contentId = contentId,
|
||||||
|
creatorId = audioContent.member!!.id,
|
||||||
|
container = "ios"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
applicationEventPublisher.publishEvent(
|
||||||
|
FcmEvent(
|
||||||
|
type = FcmEventType.UPLOAD_CONTENT,
|
||||||
|
title = audioContent.member!!.nickname,
|
||||||
|
message = "콘텐츠를 업로드 하였습니다. - ${audioContent.title}",
|
||||||
|
isAuth = audioContent.isAdult,
|
||||||
|
contentId = contentId,
|
||||||
|
creatorId = audioContent.member!!.id,
|
||||||
|
container = "aos"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
fun releaseContent(contentId: Long) {
|
||||||
|
val audioContent = repository.findByIdOrNull(contentId)
|
||||||
|
?: throw SodaException("잘못된 요청입니다.")
|
||||||
|
|
||||||
|
audioContent.isActive = true
|
||||||
|
|
||||||
applicationEventPublisher.publishEvent(
|
applicationEventPublisher.publishEvent(
|
||||||
FcmEvent(
|
FcmEvent(
|
||||||
type = FcmEventType.UPLOAD_CONTENT,
|
type = FcmEventType.UPLOAD_CONTENT,
|
||||||
|
@ -401,7 +448,12 @@ class AudioContentService(
|
||||||
contentId = audioContent.id!!
|
contentId = audioContent.id!!
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!isExistsAudioContent && !isExistsBundleAudioContent && !audioContent.isActive) {
|
if (
|
||||||
|
!isExistsAudioContent &&
|
||||||
|
!isExistsBundleAudioContent &&
|
||||||
|
!audioContent.isActive &&
|
||||||
|
audioContent.releaseDate == null
|
||||||
|
) {
|
||||||
throw SodaException("잘못된 콘텐츠 입니다.\n다시 시도해 주세요.")
|
throw SodaException("잘못된 콘텐츠 입니다.\n다시 시도해 주세요.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,19 +477,40 @@ class AudioContentService(
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
val audioContentUrl = audioContentCloudFront.generateSignedURL(
|
val releaseDate = if (
|
||||||
resourcePath = if (
|
audioContent.releaseDate != null &&
|
||||||
isExistsAudioContent ||
|
audioContent.releaseDate!! >= LocalDateTime.now()
|
||||||
isExistsBundleAudioContent ||
|
) {
|
||||||
audioContent.member!!.id!! == member.id!! ||
|
audioContent.releaseDate!!
|
||||||
audioContent.price <= 0
|
.atZone(ZoneId.of("UTC"))
|
||||||
) {
|
.withZoneSameInstant(ZoneId.of("Asia/Seoul"))
|
||||||
audioContent.content!!
|
.toLocalDateTime()
|
||||||
} else {
|
.format(DateTimeFormatter.ofPattern("yyyy년 MM월 dd일 HH시 mm분 오픈예정"))
|
||||||
audioContent.content!!.replace("output/", "preview/")
|
} else {
|
||||||
},
|
null
|
||||||
expirationTime = 1000 * 60 * 60 * (audioContent.duration!!.split(":")[0].toLong() + 2)
|
}
|
||||||
)
|
|
||||||
|
val audioContentUrl = if (
|
||||||
|
audioContent.releaseDate == null ||
|
||||||
|
audioContent.releaseDate!! <= LocalDateTime.now() ||
|
||||||
|
creatorId == member.id!!
|
||||||
|
) {
|
||||||
|
audioContentCloudFront.generateSignedURL(
|
||||||
|
resourcePath = if (
|
||||||
|
isExistsAudioContent ||
|
||||||
|
isExistsBundleAudioContent ||
|
||||||
|
audioContent.member!!.id!! == member.id!! ||
|
||||||
|
audioContent.price <= 0
|
||||||
|
) {
|
||||||
|
audioContent.content!!
|
||||||
|
} else {
|
||||||
|
audioContent.content!!.replace("output/", "preview/")
|
||||||
|
},
|
||||||
|
expirationTime = 1000 * 60 * 60 * (audioContent.duration!!.split(":")[0].toLong() + 2)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
val tag = audioContent.audioContentHashTags
|
val tag = audioContent.audioContentHashTags
|
||||||
.map { it.hashTag!!.tag }
|
.map { it.hashTag!!.tag }
|
||||||
|
@ -483,6 +556,7 @@ class AudioContentService(
|
||||||
tag = tag,
|
tag = tag,
|
||||||
price = audioContent.price,
|
price = audioContent.price,
|
||||||
duration = audioContent.duration ?: "",
|
duration = audioContent.duration ?: "",
|
||||||
|
releaseDate = releaseDate,
|
||||||
isAdult = audioContent.isAdult,
|
isAdult = audioContent.isAdult,
|
||||||
isMosaic = audioContent.isAdult && member.auth == null,
|
isMosaic = audioContent.isAdult && member.auth == null,
|
||||||
isOnlyRental = audioContent.isOnlyRental,
|
isOnlyRental = audioContent.isOnlyRental,
|
||||||
|
@ -546,7 +620,8 @@ class AudioContentService(
|
||||||
duration = it.duration,
|
duration = it.duration,
|
||||||
likeCount = likeCount,
|
likeCount = likeCount,
|
||||||
commentCount = commentCount,
|
commentCount = commentCount,
|
||||||
isAdult = it.isAdult
|
isAdult = it.isAdult,
|
||||||
|
isScheduledToOpen = it.releaseDate != null && it.releaseDate!! > LocalDateTime.now()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@ data class CreateAudioContentRequest(
|
||||||
val detail: String,
|
val detail: String,
|
||||||
val tags: String,
|
val tags: String,
|
||||||
val price: Int,
|
val price: Int,
|
||||||
|
val timezone: String,
|
||||||
|
val releaseDate: String? = null,
|
||||||
val themeId: Long = 0,
|
val themeId: Long = 0,
|
||||||
val isAdult: Boolean = false,
|
val isAdult: Boolean = false,
|
||||||
val isGeneratePreview: Boolean = true,
|
val isGeneratePreview: Boolean = true,
|
||||||
|
|
|
@ -14,6 +14,7 @@ data class GetAudioContentDetailResponse(
|
||||||
val tag: String,
|
val tag: String,
|
||||||
val price: Int,
|
val price: Int,
|
||||||
val duration: String,
|
val duration: String,
|
||||||
|
val releaseDate: String?,
|
||||||
val isAdult: Boolean,
|
val isAdult: Boolean,
|
||||||
val isMosaic: Boolean,
|
val isMosaic: Boolean,
|
||||||
val isOnlyRental: Boolean,
|
val isOnlyRental: Boolean,
|
||||||
|
|
|
@ -14,5 +14,6 @@ data class GetAudioContentListItem(
|
||||||
val duration: String?,
|
val duration: String?,
|
||||||
val likeCount: Int,
|
val likeCount: Int,
|
||||||
val commentCount: Int,
|
val commentCount: Int,
|
||||||
val isAdult: Boolean
|
val isAdult: Boolean,
|
||||||
|
val isScheduledToOpen: Boolean
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,19 +15,8 @@ import org.springframework.web.bind.annotation.RestController
|
||||||
@RequestMapping("/audio-content/main")
|
@RequestMapping("/audio-content/main")
|
||||||
class AudioContentMainController(
|
class AudioContentMainController(
|
||||||
private val service: AudioContentMainService,
|
private val service: AudioContentMainService,
|
||||||
private val orderService: OrderService,
|
private val orderService: OrderService
|
||||||
private val manageService: AudioContentMainManageService
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@GetMapping
|
|
||||||
fun getMain(
|
|
||||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
|
||||||
) = run {
|
|
||||||
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
|
|
||||||
|
|
||||||
ApiResponse.ok(manageService.getMain(member))
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/new-content-upload-creator")
|
@GetMapping("/new-content-upload-creator")
|
||||||
fun newContentUploadCreatorList(
|
fun newContentUploadCreatorList(
|
||||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.content.main
|
|
||||||
|
|
||||||
import kr.co.vividnext.sodalive.content.AudioContentRepository
|
|
||||||
import kr.co.vividnext.sodalive.content.AudioContentService
|
|
||||||
import kr.co.vividnext.sodalive.content.order.OrderService
|
|
||||||
import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository
|
|
||||||
import kr.co.vividnext.sodalive.member.Member
|
|
||||||
import kr.co.vividnext.sodalive.member.block.BlockMemberRepository
|
|
||||||
import org.springframework.beans.factory.annotation.Value
|
|
||||||
import org.springframework.stereotype.Service
|
|
||||||
import org.springframework.transaction.annotation.Transactional
|
|
||||||
import java.time.DayOfWeek
|
|
||||||
import java.time.LocalDateTime
|
|
||||||
import java.time.temporal.TemporalAdjusters
|
|
||||||
|
|
||||||
@Service
|
|
||||||
class AudioContentMainManageService(
|
|
||||||
private val service: AudioContentMainService,
|
|
||||||
private val orderService: OrderService,
|
|
||||||
private val audioContentService: AudioContentService,
|
|
||||||
|
|
||||||
private val repository: AudioContentRepository,
|
|
||||||
private val blockMemberRepository: BlockMemberRepository,
|
|
||||||
private val audioContentThemeRepository: AudioContentThemeQueryRepository,
|
|
||||||
|
|
||||||
@Value("\${cloud.aws.cloud-front.host}")
|
|
||||||
private val imageHost: String
|
|
||||||
) {
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
fun getMain(member: Member): GetAudioContentMainResponse {
|
|
||||||
val memberId = member.id!!
|
|
||||||
val isAdult = member.auth != null
|
|
||||||
|
|
||||||
val newContentUploadCreatorList = service.getNewContentUploadCreatorList(
|
|
||||||
memberId = memberId,
|
|
||||||
isAdult = isAdult
|
|
||||||
)
|
|
||||||
|
|
||||||
val bannerList = service.getAudioContentMainBannerList(memberId = memberId, isAdult = isAdult)
|
|
||||||
|
|
||||||
val orderList = orderService.getAudioContentMainOrderList(
|
|
||||||
memberId = memberId,
|
|
||||||
limit = 20
|
|
||||||
)
|
|
||||||
|
|
||||||
// 콘텐츠 테마
|
|
||||||
val themeList = audioContentThemeRepository.getActiveThemeOfContent(isAdult = isAdult)
|
|
||||||
|
|
||||||
// 새 콘텐츠 20개 - 시간 내림차순 정렬
|
|
||||||
val newContentList = repository.findByTheme(
|
|
||||||
cloudfrontHost = imageHost,
|
|
||||||
isAdult = isAdult
|
|
||||||
)
|
|
||||||
.asSequence()
|
|
||||||
.filter {
|
|
||||||
!blockMemberRepository.isBlocked(
|
|
||||||
blockedMemberId = memberId,
|
|
||||||
memberId = it.creatorId
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.toList()
|
|
||||||
|
|
||||||
val curationList = service.getAudioContentCurationList(memberId = memberId, isAdult = isAdult)
|
|
||||||
|
|
||||||
val currentDateTime = LocalDateTime.now()
|
|
||||||
val startDate = currentDateTime
|
|
||||||
.minusWeeks(1)
|
|
||||||
.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
|
|
||||||
.withHour(15)
|
|
||||||
.withMinute(0)
|
|
||||||
.withSecond(0)
|
|
||||||
val endDate = startDate.plusDays(7)
|
|
||||||
|
|
||||||
val contentRankingSortTypeList = audioContentService.getContentRankingSortTypeList()
|
|
||||||
val contentRanking = audioContentService.getAudioContentRanking(
|
|
||||||
isAdult = isAdult,
|
|
||||||
startDate = startDate,
|
|
||||||
endDate = endDate,
|
|
||||||
offset = 0,
|
|
||||||
limit = 12
|
|
||||||
)
|
|
||||||
|
|
||||||
return GetAudioContentMainResponse(
|
|
||||||
newContentUploadCreatorList = newContentUploadCreatorList,
|
|
||||||
bannerList = bannerList,
|
|
||||||
orderList = orderList,
|
|
||||||
themeList = themeList,
|
|
||||||
newContentList = newContentList,
|
|
||||||
curationList = curationList,
|
|
||||||
contentRankingSortTypeList = contentRankingSortTypeList,
|
|
||||||
contentRanking = contentRanking
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -33,6 +33,7 @@ class AudioContentMainService(
|
||||||
fun getNewContentByTheme(theme: String, member: Member, pageable: Pageable): List<GetAudioContentMainItem> {
|
fun getNewContentByTheme(theme: String, member: Member, pageable: Pageable): List<GetAudioContentMainItem> {
|
||||||
return repository.findByTheme(
|
return repository.findByTheme(
|
||||||
cloudfrontHost = imageHost,
|
cloudfrontHost = imageHost,
|
||||||
|
memberId = member.id!!,
|
||||||
theme = theme,
|
theme = theme,
|
||||||
isAdult = member.auth != null,
|
isAdult = member.auth != null,
|
||||||
offset = pageable.offset,
|
offset = pageable.offset,
|
||||||
|
@ -45,9 +46,11 @@ class AudioContentMainService(
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
fun getNewContentFor2WeeksByTheme(theme: String, member: Member, pageable: Pageable): GetNewContentAllResponse {
|
fun getNewContentFor2WeeksByTheme(theme: String, member: Member, pageable: Pageable): GetNewContentAllResponse {
|
||||||
val totalCount = repository.totalCountNewContentFor2Weeks(theme, isAdult = member.auth != null)
|
val totalCount =
|
||||||
|
repository.totalCountNewContentFor2Weeks(theme, memberId = member.id!!, isAdult = member.auth != null)
|
||||||
val items = repository.findByThemeFor2Weeks(
|
val items = repository.findByThemeFor2Weeks(
|
||||||
cloudfrontHost = imageHost,
|
cloudfrontHost = imageHost,
|
||||||
|
memberId = member.id!!,
|
||||||
theme = theme,
|
theme = theme,
|
||||||
isAdult = member.auth != null,
|
isAdult = member.auth != null,
|
||||||
offset = pageable.offset,
|
offset = pageable.offset,
|
||||||
|
@ -119,31 +122,6 @@ class AudioContentMainService(
|
||||||
}
|
}
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
@Cacheable(cacheNames = ["default"], key = "'contentCurationList:' + #memberId + ':' + #isAdult")
|
|
||||||
fun getAudioContentCurationList(memberId: Long, isAdult: Boolean) =
|
|
||||||
repository.getAudioContentCurations(isAdult = isAdult)
|
|
||||||
.asSequence()
|
|
||||||
.map {
|
|
||||||
GetAudioContentCurationResponse(
|
|
||||||
curationId = it.id!!,
|
|
||||||
title = it.title,
|
|
||||||
description = it.description,
|
|
||||||
contents = repository.findAudioContentByCurationId(
|
|
||||||
curationId = it.id!!,
|
|
||||||
cloudfrontHost = imageHost,
|
|
||||||
isAdult = isAdult
|
|
||||||
)
|
|
||||||
.asSequence()
|
|
||||||
.filter { content ->
|
|
||||||
!blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = content.creatorId)
|
|
||||||
}
|
|
||||||
.toList()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.filter { it.contents.isNotEmpty() }
|
|
||||||
.toList()
|
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
@Cacheable(
|
@Cacheable(
|
||||||
cacheNames = ["default"],
|
cacheNames = ["default"],
|
||||||
|
|
|
@ -161,6 +161,7 @@ class OrderQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : Orde
|
||||||
.from(order)
|
.from(order)
|
||||||
.where(
|
.where(
|
||||||
order.member.id.eq(memberId)
|
order.member.id.eq(memberId)
|
||||||
|
.and(order.isActive.isTrue)
|
||||||
.and(
|
.and(
|
||||||
order.type.eq(OrderType.KEEP)
|
order.type.eq(OrderType.KEEP)
|
||||||
.or(
|
.or(
|
||||||
|
@ -199,6 +200,7 @@ class OrderQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : Orde
|
||||||
.innerJoin(audioContent.member, member)
|
.innerJoin(audioContent.member, member)
|
||||||
.where(
|
.where(
|
||||||
order.member.id.eq(memberId)
|
order.member.id.eq(memberId)
|
||||||
|
.and(order.isActive.isTrue)
|
||||||
.and(
|
.and(
|
||||||
order.type.eq(OrderType.KEEP)
|
order.type.eq(OrderType.KEEP)
|
||||||
.or(
|
.or(
|
||||||
|
|
|
@ -97,7 +97,7 @@ class AuthService(
|
||||||
|
|
||||||
repository.save(auth)
|
repository.save(auth)
|
||||||
} else {
|
} else {
|
||||||
throw SodaException("19세 미만 인증 오류")
|
throw SodaException("2005년 1월 1일 이전 출생자만 본인인증이 가능합니다.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue