19금 콘텐츠 보기 설정 적용 #289

Merged
klaus merged 3 commits from test into main 2025-03-19 02:05:17 +00:00
27 changed files with 963 additions and 194 deletions

View File

@ -77,6 +77,7 @@ interface AudioContentQueryRepository {
memberId: Long,
theme: List<String>,
isAdult: Boolean = false,
contentType: ContentType,
offset: Long = 0,
limit: Long = 20
): List<GetAudioContentMainItem>
@ -84,7 +85,8 @@ interface AudioContentQueryRepository {
fun totalAlarmCountByTheme(
memberId: Long,
theme: List<String>,
isAdult: Boolean = false
isAdult: Boolean = false,
contentType: ContentType
): Int
fun totalCountByTheme(
@ -130,6 +132,7 @@ interface AudioContentQueryRepository {
curationId: Long,
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
offset: Long = 0,
limit: Long = 20
): List<GetAudioContentMainItem>
@ -401,7 +404,15 @@ class AudioContentQueryRepositoryImpl(
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.auth.gender.eq(if (contentType == ContentType.MALE) 0 else 1)
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
@ -444,6 +455,7 @@ class AudioContentQueryRepositoryImpl(
memberId: Long,
theme: List<String>,
isAdult: Boolean,
contentType: ContentType,
offset: Long,
limit: Long
): List<GetAudioContentMainItem> {
@ -464,6 +476,20 @@ class AudioContentQueryRepositoryImpl(
if (!isAdult) {
where = where.and(audioContent.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
if (theme.isNotEmpty()) {
@ -494,7 +520,12 @@ class AudioContentQueryRepositoryImpl(
.fetch()
}
override fun totalAlarmCountByTheme(memberId: Long, theme: List<String>, isAdult: Boolean): Int {
override fun totalAlarmCountByTheme(
memberId: Long,
theme: List<String>,
isAdult: Boolean,
contentType: ContentType
): Int {
val blockMemberCondition = blockMember.member.id.eq(member.id)
.and(blockMember.isActive.isTrue)
.and(blockMember.blockedMember.id.eq(memberId))
@ -510,6 +541,20 @@ class AudioContentQueryRepositoryImpl(
if (!isAdult) {
where = where.and(audioContent.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
if (theme.isNotEmpty()) {
@ -546,7 +591,15 @@ class AudioContentQueryRepositoryImpl(
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.auth.gender.eq(if (contentType == ContentType.MALE) 0 else 1)
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
@ -586,7 +639,15 @@ class AudioContentQueryRepositoryImpl(
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.auth.gender.eq(if (contentType == ContentType.MALE) 0 else 1)
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
@ -633,7 +694,15 @@ class AudioContentQueryRepositoryImpl(
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.auth.gender.eq(if (contentType == ContentType.MALE) 0 else 1)
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
@ -751,7 +820,15 @@ class AudioContentQueryRepositoryImpl(
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.auth.gender.eq(if (contentType == ContentType.MALE) 0 else 1)
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
@ -783,6 +860,7 @@ class AudioContentQueryRepositoryImpl(
curationId: Long,
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
offset: Long,
limit: Long
): List<GetAudioContentMainItem> {
@ -801,6 +879,20 @@ class AudioContentQueryRepositoryImpl(
if (!isAdult) {
where = where.and(audioContent.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory

View File

@ -83,11 +83,18 @@ class AudioContentMainController(
@GetMapping("/theme")
fun getThemeList(
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(service.getThemeList(isAdult = member.auth != null))
ApiResponse.ok(
service.getThemeList(
isAdult = member.auth != null && (isAdultContentVisible ?: true),
contentType = contentType ?: ContentType.ALL
)
)
}
@GetMapping("/new/all")

View File

@ -26,8 +26,8 @@ class AudioContentMainService(
) {
@Transactional(readOnly = true)
@Cacheable(cacheNames = ["default"], key = "'themeList:' + ':' + #isAdult")
fun getThemeList(isAdult: Boolean): List<String> {
return audioContentThemeRepository.getActiveThemeOfContent(isAdult = isAdult)
fun getThemeList(isAdult: Boolean, contentType: ContentType): List<String> {
return audioContentThemeRepository.getActiveThemeOfContent(isAdult = isAdult, contentType = contentType)
.filter {
it != "모닝콜" &&
it != "알람" &&
@ -73,17 +73,20 @@ class AudioContentMainService(
): GetNewContentAllResponse {
val isAdult = member.auth != null && isAdultContentVisible
val themeList = if (theme.isBlank()) {
audioContentThemeRepository.getActiveThemeOfContent(isAdult = isAdult, isFree = isFree)
.filter {
it != "모닝콜" &&
it != "알람" &&
it != "슬립콜" &&
it != "다시듣기" &&
it != "ASMR" &&
it != "릴레이" &&
it != "챌린지" &&
it != "자기소개"
}
audioContentThemeRepository.getActiveThemeOfContent(
isAdult = isAdult,
isFree = isFree,
contentType = contentType
).filter {
it != "모닝콜" &&
it != "알람" &&
it != "슬립콜" &&
it != "다시듣기" &&
it != "ASMR" &&
it != "릴레이" &&
it != "챌린지" &&
it != "자기소개"
}
} else {
listOf(theme)
}

View File

@ -23,7 +23,15 @@ class AudioContentCurationQueryRepository(private val queryFactory: JPAQueryFact
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.auth.gender.eq(if (contentType == ContentType.MALE) 0 else 1)
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
@ -31,6 +39,7 @@ class AudioContentCurationQueryRepository(private val queryFactory: JPAQueryFact
return queryFactory
.select(audioContent.id)
.from(audioContent)
.innerJoin(audioContent.member, member)
.where(where)
.fetch()
.size
@ -62,7 +71,15 @@ class AudioContentCurationQueryRepository(private val queryFactory: JPAQueryFact
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.auth.gender.eq(if (contentType == ContentType.MALE) 0 else 1)
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}

View File

@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.content.main.tab
import com.querydsl.core.types.dsl.Expressions
import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
import kr.co.vividnext.sodalive.content.main.ContentCreatorResponse
import kr.co.vividnext.sodalive.content.main.QContentCreatorResponse
@ -22,13 +23,15 @@ class AudioContentMainTabRepository(
fun findCreatorByThemeContent(
memberId: Long,
theme: String,
minCount: Int
minCount: Int,
isAdult: Boolean,
contentType: ContentType
): List<ContentCreatorResponse> {
val blockMemberCondition = blockMember.member.id.eq(member.id)
.and(blockMember.isActive.isTrue)
.and(blockMember.blockedMember.id.eq(memberId))
val where = member.isActive.isTrue
var where = member.isActive.isTrue
.and(member.role.eq(MemberRole.CREATOR))
.and(audioContent.isActive.isTrue)
.and(audioContent.price.gt(0))
@ -38,6 +41,24 @@ class AudioContentMainTabRepository(
.and(audioContentTheme.theme.eq(theme))
.and(blockMember.id.isNull)
if (!isAdult) {
where = where.and(audioContent.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory
.select(
QContentCreatorResponse(
@ -61,12 +82,17 @@ class AudioContentMainTabRepository(
.fetch()
}
fun findCreatorWithHasFreeContent(memberId: Long, minCount: Int): List<ContentCreatorResponse> {
fun findCreatorWithHasFreeContent(
memberId: Long,
minCount: Int,
isAdult: Boolean,
contentType: ContentType
): List<ContentCreatorResponse> {
val blockMemberCondition = blockMember.member.id.eq(member.id)
.and(blockMember.isActive.isTrue)
.and(blockMember.blockedMember.id.eq(memberId))
val where = member.isActive.isTrue
var where = member.isActive.isTrue
.and(member.role.eq(MemberRole.CREATOR))
.and(audioContent.isActive.isTrue)
.and(audioContent.price.loe(0))
@ -74,6 +100,24 @@ class AudioContentMainTabRepository(
.and(audioContent.limited.isNull)
.and(blockMember.id.isNull)
if (!isAdult) {
where = where.and(audioContent.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory
.select(
QContentCreatorResponse(

View File

@ -1,6 +1,7 @@
package kr.co.vividnext.sodalive.content.main.tab
import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.content.main.tab.QRecommendSeries.recommendSeries
import kr.co.vividnext.sodalive.creator.admin.content.series.QSeries.series
import kr.co.vividnext.sodalive.member.QMember.member
@ -14,13 +15,27 @@ class RecommendSeriesRepository(
@Value("\${cloud.aws.cloud-front.host}")
private val imageHost: String
) {
fun getNewSeriesList(isAdult: Boolean): List<GetRecommendSeriesListResponse> {
fun getNewSeriesList(isAdult: Boolean, contentType: ContentType): List<GetRecommendSeriesListResponse> {
var where = recommendSeries.isActive.isTrue
.and(recommendSeries.isFree.isFalse)
.and(series.isActive.isTrue)
if (!isAdult) {
where = where.and(series.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
series.member.isNull.or(
series.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory
@ -42,13 +57,27 @@ class RecommendSeriesRepository(
.fetch()
}
fun getRecommendSeriesList(isAdult: Boolean): List<GetRecommendSeriesListResponse> {
fun getRecommendSeriesList(isAdult: Boolean, contentType: ContentType): List<GetRecommendSeriesListResponse> {
var where = recommendSeries.isActive.isTrue
.and(recommendSeries.isFree.isTrue)
.and(series.isActive.isTrue)
if (!isAdult) {
where = where.and(series.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
series.member.isNull.or(
series.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory

View File

@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.content.main.tab.alarm
import kr.co.vividnext.sodalive.common.ApiResponse
import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.member.Member
import org.springframework.data.domain.Pageable
import org.springframework.security.core.annotation.AuthenticationPrincipal
@ -15,16 +16,26 @@ import org.springframework.web.bind.annotation.RestController
class AudioContentMainTabAlarmController(private val service: AudioContentMainTabAlarmService) {
@GetMapping
fun fetchContentMainTabAlarm(
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(service.fetchData(member))
ApiResponse.ok(
service.fetchData(
isAdultContentVisible = isAdultContentVisible ?: true,
contentType = contentType ?: ContentType.ALL,
member
)
)
}
@GetMapping("/all")
fun fetchAlarmContentByTheme(
@RequestParam("theme") theme: String,
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
pageable: Pageable
) = run {
@ -34,6 +45,8 @@ class AudioContentMainTabAlarmController(private val service: AudioContentMainTa
service.fetchAlarmContentByTheme(
theme,
member,
isAdultContentVisible = isAdultContentVisible ?: true,
contentType = contentType ?: ContentType.ALL,
offset = pageable.offset,
limit = pageable.pageSize.toLong()
)

View File

@ -1,6 +1,7 @@
package kr.co.vividnext.sodalive.content.main.tab.alarm
import kr.co.vividnext.sodalive.content.AudioContentRepository
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.content.main.GetNewContentAllResponse
import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerService
import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationQueryRepository
@ -21,8 +22,12 @@ class AudioContentMainTabAlarmService(
private val eventService: EventService,
private val curationRepository: AudioContentCurationQueryRepository
) {
fun fetchData(member: Member): GetContentMainTabAlarmResponse {
val isAdult = member.auth != null
fun fetchData(
isAdultContentVisible: Boolean,
contentType: ContentType,
member: Member
): GetContentMainTabAlarmResponse {
val isAdult = member.auth != null && isAdultContentVisible
val memberId = member.id!!
val contentBannerList = bannerService.getBannerList(
@ -36,6 +41,7 @@ class AudioContentMainTabAlarmService(
memberId = memberId,
theme = alarmThemeList,
isAdult = isAdult,
contentType = contentType,
limit = 10
)
@ -53,6 +59,7 @@ class AudioContentMainTabAlarmService(
val rankAlarmContentList = rankingService.getContentRanking(
memberId = memberId,
isAdult = isAdult,
contentType = contentType,
startDate = startDate,
endDate = endDate,
theme = alarmThemeList[0]
@ -66,10 +73,12 @@ class AudioContentMainTabAlarmService(
items = contentRepository.findAudioContentByCurationIdV2(
curationId = it.id!!,
memberId = memberId,
isAdult = isAdult
isAdult = isAdult,
contentType = contentType
)
)
}
.filter { it.items.isNotEmpty() }
return GetContentMainTabAlarmResponse(
contentBannerList = contentBannerList,
@ -84,6 +93,8 @@ class AudioContentMainTabAlarmService(
fun fetchAlarmContentByTheme(
theme: String,
member: Member,
isAdultContentVisible: Boolean,
contentType: ContentType,
offset: Long,
limit: Long
): GetNewContentAllResponse {
@ -94,18 +105,20 @@ class AudioContentMainTabAlarmService(
}
val memberId = member.id!!
val isAdult = member.auth != null
val isAdult = member.auth != null && isAdultContentVisible
val totalCount = contentRepository.totalAlarmCountByTheme(
memberId = memberId,
theme = alarmThemeList,
isAdult = isAdult
isAdult = isAdult,
contentType = contentType
)
val items = contentRepository.findAlarmContentByTheme(
memberId = memberId,
theme = alarmThemeList,
isAdult = isAdult,
contentType = contentType,
offset = offset,
limit = limit
)

View File

@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.content.main.tab.asmr
import kr.co.vividnext.sodalive.common.ApiResponse
import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.member.Member
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.GetMapping
@ -14,16 +15,26 @@ import org.springframework.web.bind.annotation.RestController
class AudioContentMainTabAsmrController(private val service: AudioContentMainTabAsmrService) {
@GetMapping
fun fetchContentMainTabAsmr(
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(service.fetchData(member))
ApiResponse.ok(
service.fetchData(
isAdultContentVisible = isAdultContentVisible ?: true,
contentType = contentType ?: ContentType.ALL,
member
)
)
}
@GetMapping("/popular-content-by-creator")
fun getPopularContentByCreator(
@RequestParam creatorId: Long,
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
@ -31,7 +42,8 @@ class AudioContentMainTabAsmrController(private val service: AudioContentMainTab
ApiResponse.ok(
service.getPopularContentByCreator(
creatorId = creatorId,
isAdult = member.auth != null
isAdult = member.auth != null && (isAdultContentVisible ?: true),
contentType = contentType ?: ContentType.ALL
)
)
}

View File

@ -21,8 +21,12 @@ class AudioContentMainTabAsmrService(
private val eventService: EventService,
private val curationRepository: AudioContentCurationQueryRepository
) {
fun fetchData(member: Member): GetContentMainTabAsmrResponse {
val isAdult = member.auth != null
fun fetchData(
isAdultContentVisible: Boolean,
contentType: ContentType,
member: Member
): GetContentMainTabAsmrResponse {
val isAdult = member.auth != null && isAdultContentVisible
val memberId = member.id!!
val theme = "ASMR"
val tabId = 5L
@ -37,20 +41,23 @@ class AudioContentMainTabAsmrService(
memberId = memberId,
theme = listOf(theme),
isAdult = isAdult,
contentType = ContentType.ALL,
contentType = contentType,
limit = 10
)
val creatorList = repository.findCreatorByThemeContent(
memberId = memberId,
theme = theme,
minCount = 4
minCount = 4,
isAdult = isAdult,
contentType = contentType
)
val salesCountRankContentList = if (creatorList.isNotEmpty()) {
rankingService.fetchCreatorContentBySalesCountTop4(
creatorId = creatorList[0].creatorId,
isAdult = isAdult,
contentType = contentType,
theme = theme
)
} else {
@ -66,10 +73,12 @@ class AudioContentMainTabAsmrService(
items = contentRepository.findAudioContentByCurationIdV2(
curationId = it.id!!,
memberId = memberId,
isAdult = isAdult
isAdult = isAdult,
contentType = contentType
)
)
}
.filter { it.items.isNotEmpty() }
return GetContentMainTabAsmrResponse(
contentBannerList = contentBannerList,
@ -81,10 +90,15 @@ class AudioContentMainTabAsmrService(
)
}
fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): List<GetAudioContentRankingItem> {
fun getPopularContentByCreator(
creatorId: Long,
isAdult: Boolean,
contentType: ContentType
): List<GetAudioContentRankingItem> {
return rankingService.fetchCreatorContentBySalesCountTop4(
creatorId = creatorId,
isAdult = isAdult,
contentType = contentType,
theme = "ASMR"
)
}

View File

@ -34,6 +34,8 @@ class AudioContentMainTabContentController(private val service: AudioContentMain
@GetMapping("/ranking")
fun getAudioContentRanking(
@RequestParam("sort-type", required = false) sortType: String?,
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
pageable: Pageable
) = run {
@ -42,7 +44,8 @@ class AudioContentMainTabContentController(private val service: AudioContentMain
ApiResponse.ok(
service.getAudioContentRanking(
memberId = member.id!!,
isAdult = member.auth != null,
isAdult = member.auth != null && (isAdultContentVisible ?: true),
contentType = contentType ?: ContentType.ALL,
sortType = sortType ?: "매출"
)
)
@ -71,6 +74,8 @@ class AudioContentMainTabContentController(private val service: AudioContentMain
@GetMapping("/popular-content-by-creator")
fun getPopularContentByCreator(
@RequestParam creatorId: Long,
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
@ -78,7 +83,8 @@ class AudioContentMainTabContentController(private val service: AudioContentMain
ApiResponse.ok(
service.getPopularContentByCreator(
creatorId = creatorId,
isAdult = member.auth != null
isAdult = member.auth != null && (isAdultContentVisible ?: true),
contentType = contentType ?: ContentType.ALL
)
)
}
@ -86,11 +92,16 @@ class AudioContentMainTabContentController(private val service: AudioContentMain
@GetMapping("/recommend-content-by-tag")
fun getRecommendedContentByTag(
@RequestParam tag: String,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(
service.getRecommendedContentByTag(memberId = member.id!!, tag = tag)
service.getRecommendedContentByTag(
memberId = member.id!!,
tag = tag,
contentType = contentType ?: ContentType.ALL
)
)
}
}

View File

@ -30,7 +30,7 @@ class AudioContentMainTabContentService(
member: Member
): GetContentMainTabContentResponse {
val memberId = member.id!!
val isAdult = member.auth != null
val isAdult = member.auth != null && isAdultContentVisible
val tabId = 3L
// 단편 배너
@ -41,24 +41,26 @@ class AudioContentMainTabContentService(
)
// 새로운 단편 테마
val themeOfContentList = audioContentThemeRepository.getActiveThemeOfContent(isAdult = isAdult)
.filter {
it != "모닝콜" &&
it != "알람" &&
it != "슬립콜" &&
it != "다시듣기" &&
it != "ASMR" &&
it != "릴레이" &&
it != "챌린지" &&
it != "자기소개"
}
val themeOfContentList = audioContentThemeRepository.getActiveThemeOfContent(
isAdult = isAdult,
contentType = contentType
).filter {
it != "모닝콜" &&
it != "알람" &&
it != "슬립콜" &&
it != "다시듣기" &&
it != "ASMR" &&
it != "릴레이" &&
it != "챌린지" &&
it != "자기소개"
}
// 새로운 단편
val newContentList = audioContentRepository.findByTheme(
memberId = member.id!!,
theme = themeOfContentList,
isAdult = member.auth != null,
contentType = ContentType.ALL,
isAdult = isAdult,
contentType = contentType,
offset = 0,
limit = 10
)
@ -76,6 +78,7 @@ class AudioContentMainTabContentService(
val rankContentList = rankingService.getContentRanking(
memberId = memberId,
isAdult = isAdult,
contentType = contentType,
startDate = dailyRankingStartDate,
endDate = dailyRankingEndDate
)
@ -85,6 +88,7 @@ class AudioContentMainTabContentService(
val contentRankCreatorList = rankingService.fetchCreatorBySellContentCountRankTop20(
memberId = member.id!!,
contentType = contentType,
startDate = dailyRankingStartDate,
endDate = dailyRankingEndDate
)
@ -92,20 +96,25 @@ class AudioContentMainTabContentService(
val likeCountRankContentList = if (contentRankCreatorList.isNotEmpty()) {
rankingService.fetchCreatorContentByLikeCountTop4(
creatorId = contentRankCreatorList[0].creatorId,
isAdult = member.auth != null
isAdult = isAdult,
contentType = contentType
)
} else {
emptyList()
}
val tagList = if (isAdult) {
tagCurationService.getTagList(isAdult = isAdult)
tagCurationService.getTagList(isAdult = isAdult, contentType = contentType)
} else {
emptyList()
}
val tagCurationContentList = if (tagList.isNotEmpty()) {
tagCurationService.getTagCurationContentList(memberId = memberId, tag = tagList[0])
tagCurationService.getTagCurationContentList(
memberId = memberId,
tag = tagList[0],
contentType = contentType
)
} else {
emptyList()
}
@ -117,10 +126,12 @@ class AudioContentMainTabContentService(
items = audioContentRepository.findAudioContentByCurationIdV2(
curationId = it.id!!,
memberId = memberId,
isAdult = isAdult
isAdult = isAdult,
contentType = contentType
)
)
}
.filter { it.items.isNotEmpty() }
return GetContentMainTabContentResponse(
bannerList = contentBannerList,
@ -141,6 +152,7 @@ class AudioContentMainTabContentService(
fun getAudioContentRanking(
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
sortType: String
): List<GetAudioContentRankingItem> {
val currentDateTime = LocalDateTime.now()
@ -155,6 +167,7 @@ class AudioContentMainTabContentService(
return rankingService.getContentRanking(
memberId = memberId,
isAdult = isAdult,
contentType = contentType,
startDate = dailyRankingStartDate,
endDate = dailyRankingEndDate,
sortType = sortType
@ -170,7 +183,7 @@ class AudioContentMainTabContentService(
val isAdult = member.auth != null && isAdultContentVisible
val themeList = if (theme.isBlank()) {
audioContentThemeRepository.getActiveThemeOfContent(isAdult = isAdult)
audioContentThemeRepository.getActiveThemeOfContent(isAdult = isAdult, contentType = contentType)
.filter {
it != "모닝콜" &&
it != "알람" &&
@ -195,14 +208,23 @@ class AudioContentMainTabContentService(
)
}
fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): List<GetAudioContentRankingItem> {
fun getPopularContentByCreator(
creatorId: Long,
isAdult: Boolean,
contentType: ContentType
): List<GetAudioContentRankingItem> {
return rankingService.fetchCreatorContentByLikeCountTop4(
creatorId = creatorId,
isAdult = isAdult
isAdult = isAdult,
contentType = contentType
)
}
fun getRecommendedContentByTag(memberId: Long, tag: String): List<GetAudioContentMainItem> {
return tagCurationService.getTagCurationContentList(memberId = memberId, tag = tag)
fun getRecommendedContentByTag(
memberId: Long,
tag: String,
contentType: ContentType
): List<GetAudioContentMainItem> {
return tagCurationService.getTagCurationContentList(memberId = memberId, tag = tag, contentType = contentType)
}
}

View File

@ -1,6 +1,7 @@
package kr.co.vividnext.sodalive.content.main.tab.content
import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem
import kr.co.vividnext.sodalive.content.main.QGetAudioContentMainItem
@ -18,7 +19,7 @@ class ContentMainTabTagCurationRepository(
@Value("\${cloud.aws.cloud-front.host}")
private val imageHost: String
) {
fun getTagList(isAdult: Boolean): List<String> {
fun getTagList(isAdult: Boolean, contentType: ContentType): List<String> {
var where = contentHashTagCuration.isActive.isTrue
.and(audioContent.isActive.isTrue)
.and(audioContent.duration.isNotNull)
@ -27,6 +28,20 @@ class ContentMainTabTagCurationRepository(
if (!isAdult) {
where = where.and(contentHashTagCuration.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory
@ -42,18 +57,36 @@ class ContentMainTabTagCurationRepository(
.fetch()
}
fun getTagCurationContentList(memberId: Long, tag: String): List<GetAudioContentMainItem> {
fun getTagCurationContentList(
memberId: Long,
tag: String,
contentType: ContentType
): List<GetAudioContentMainItem> {
val blockMemberCondition = blockMember.member.id.eq(member.id)
.and(blockMember.isActive.isTrue)
.and(blockMember.blockedMember.id.eq(memberId))
val where = audioContent.isActive.isTrue
var where = audioContent.isActive.isTrue
.and(audioContent.duration.isNotNull)
.and(audioContent.limited.isNull)
.and(blockMember.id.isNull)
.and(contentHashTagCurationItem.isActive.isTrue)
.and(contentHashTagCuration.tag.eq(tag))
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
return queryFactory
.select(
QGetAudioContentMainItem(

View File

@ -1,15 +1,20 @@
package kr.co.vividnext.sodalive.content.main.tab.content
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem
import org.springframework.stereotype.Service
@Service
class ContentMainTabTagCurationService(private val repository: ContentMainTabTagCurationRepository) {
fun getTagList(isAdult: Boolean): List<String> {
return repository.getTagList(isAdult = isAdult)
fun getTagList(isAdult: Boolean, contentType: ContentType): List<String> {
return repository.getTagList(isAdult = isAdult, contentType = contentType)
}
fun getTagCurationContentList(memberId: Long, tag: String): List<GetAudioContentMainItem> {
return repository.getTagCurationContentList(memberId = memberId, tag = tag)
fun getTagCurationContentList(
memberId: Long,
tag: String,
contentType: ContentType
): List<GetAudioContentMainItem> {
return repository.getTagCurationContentList(memberId = memberId, tag = tag, contentType = contentType)
}
}

View File

@ -16,15 +16,25 @@ import org.springframework.web.bind.annotation.RestController
class AudioContentMainTabFreeController(private val service: AudioContentMainTabFreeService) {
@GetMapping
fun fetchContentMainFree(
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(service.fetchData(member))
ApiResponse.ok(
service.fetchData(
isAdultContentVisible = isAdultContentVisible ?: true,
contentType = contentType ?: ContentType.ALL,
member
)
)
}
@GetMapping("/introduce-creator")
fun getIntroduceCreator(
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
pageable: Pageable
) = run {
@ -33,6 +43,8 @@ class AudioContentMainTabFreeController(private val service: AudioContentMainTab
ApiResponse.ok(
service.getIntroduceCreator(
member,
isAdultContentVisible = isAdultContentVisible ?: true,
contentType = contentType ?: ContentType.ALL,
offset = pageable.offset,
limit = pageable.pageSize.toLong()
)
@ -64,6 +76,8 @@ class AudioContentMainTabFreeController(private val service: AudioContentMainTab
@GetMapping("/popular-content-by-creator")
fun getPopularContentByCreator(
@RequestParam creatorId: Long,
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
@ -71,7 +85,8 @@ class AudioContentMainTabFreeController(private val service: AudioContentMainTab
ApiResponse.ok(
service.getPopularContentByCreator(
creatorId = creatorId,
isAdult = member.auth != null
isAdult = member.auth != null && (isAdultContentVisible ?: true),
contentType = contentType ?: ContentType.ALL
)
)
}

View File

@ -25,8 +25,12 @@ class AudioContentMainTabFreeService(
private val audioContentRepository: AudioContentRepository,
private val audioContentThemeRepository: AudioContentThemeQueryRepository
) {
fun fetchData(member: Member): GetContentMainTabFreeResponse {
val isAdult = member.auth != null
fun fetchData(
isAdultContentVisible: Boolean,
contentType: ContentType,
member: Member
): GetContentMainTabFreeResponse {
val isAdult = member.auth != null && isAdultContentVisible
val memberId = member.id!!
val tabId = 7L
@ -40,37 +44,43 @@ class AudioContentMainTabFreeService(
tabId = tabId,
title = "크리에이터 소개",
isAdult = isAdult
)
.map {
GetContentCurationResponse(
title = it.title,
items = contentRepository.findAudioContentByCurationIdV2(
curationId = it.id!!,
memberId = memberId,
isAdult = isAdult
)
).map {
GetContentCurationResponse(
title = it.title,
items = contentRepository.findAudioContentByCurationIdV2(
curationId = it.id!!,
memberId = memberId,
isAdult = isAdult,
contentType = contentType
)
}
)
}.filter { it.items.isNotEmpty() }
val recommendSeriesList = recommendSeriesRepository.getRecommendSeriesList(isAdult = isAdult)
val recommendSeriesList = recommendSeriesRepository.getRecommendSeriesList(
isAdult = isAdult,
contentType = contentType
)
val themeList = audioContentThemeRepository.getActiveThemeOfContent(isAdult = isAdult, isFree = true)
.filter {
it != "모닝콜" &&
it != "알람" &&
it != "슬립콜" &&
it != "다시듣기" &&
it != "ASMR" &&
it != "릴레이" &&
it != "챌린지" &&
it != "자기소개"
}
val themeList = audioContentThemeRepository.getActiveThemeOfContent(
isAdult = isAdult,
isFree = true,
contentType = contentType
).filter {
it != "모닝콜" &&
it != "알람" &&
it != "슬립콜" &&
it != "다시듣기" &&
it != "ASMR" &&
it != "릴레이" &&
it != "챌린지" &&
it != "자기소개"
}
val newFreeContentList = if (themeList.isNotEmpty()) {
audioContentRepository.findByTheme(
memberId = member.id!!,
theme = themeList,
isAdult = member.auth != null,
contentType = ContentType.ALL,
isAdult = isAdult,
contentType = contentType,
offset = 0,
limit = 10,
isFree = true
@ -79,9 +89,9 @@ class AudioContentMainTabFreeService(
emptyList()
}
val creatorList = repository.findCreatorWithHasFreeContent(memberId, 4)
val creatorList = repository.findCreatorWithHasFreeContent(memberId, 4, isAdult, contentType)
val playCountRankContentList = if (creatorList.isNotEmpty()) {
rankingService.fetchFreeContentByCreatorIdTop4(creatorList[0].creatorId, isAdult)
rankingService.fetchFreeContentByCreatorIdTop4(creatorList[0].creatorId, isAdult, contentType)
} else {
emptyList()
}
@ -94,10 +104,12 @@ class AudioContentMainTabFreeService(
items = contentRepository.findAudioContentByCurationIdV2(
curationId = it.id!!,
memberId = memberId,
isAdult = isAdult
isAdult = isAdult,
contentType = contentType
)
)
}
.filter { it.items.isNotEmpty() }
return GetContentMainTabFreeResponse(
contentBannerList = contentBannerList,
@ -115,8 +127,14 @@ class AudioContentMainTabFreeService(
)
}
fun getIntroduceCreator(member: Member, offset: Long, limit: Long): List<GetAudioContentMainItem> {
val isAdult = member.auth != null
fun getIntroduceCreator(
member: Member,
isAdultContentVisible: Boolean,
contentType: ContentType,
offset: Long,
limit: Long
): List<GetAudioContentMainItem> {
val isAdult = member.auth != null && isAdultContentVisible
val memberId = member.id!!
val introduceCreatorCuration = curationRepository.findByContentMainTabIdAndTitle(
@ -130,6 +148,7 @@ class AudioContentMainTabFreeService(
curationId = introduceCreatorCuration[0].id!!,
memberId = memberId,
isAdult = isAdult,
contentType = contentType,
offset = offset,
limit = limit
)
@ -153,18 +172,18 @@ class AudioContentMainTabFreeService(
} else {
audioContentThemeRepository.getActiveThemeOfContent(
isAdult = member.auth != null && isAdultContentVisible,
isFree = true
)
.filter {
it != "모닝콜" &&
it != "알람" &&
it != "슬립콜" &&
it != "다시듣기" &&
it != "ASMR" &&
it != "릴레이" &&
it != "챌린지" &&
it != "자기소개"
}
isFree = true,
contentType = contentType
).filter {
it != "모닝콜" &&
it != "알람" &&
it != "슬립콜" &&
it != "다시듣기" &&
it != "ASMR" &&
it != "릴레이" &&
it != "챌린지" &&
it != "자기소개"
}
},
isAdult = member.auth != null && isAdultContentVisible,
contentType = contentType,
@ -174,7 +193,11 @@ class AudioContentMainTabFreeService(
)
}
fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): List<GetAudioContentRankingItem> {
return rankingService.fetchFreeContentByCreatorIdTop4(creatorId, isAdult)
fun getPopularContentByCreator(
creatorId: Long,
isAdult: Boolean,
contentType: ContentType
): List<GetAudioContentRankingItem> {
return rankingService.fetchFreeContentByCreatorIdTop4(creatorId, isAdult, contentType)
}
}

View File

@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.content.main.tab.home
import kr.co.vividnext.sodalive.common.ApiResponse
import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.member.Member
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.GetMapping
@ -14,16 +15,26 @@ import org.springframework.web.bind.annotation.RestController
class AudioContentMainTabHomeController(private val service: AudioContentMainTabHomeService) {
@GetMapping
fun fetchContentMainHome(
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(service.fetchData(member))
ApiResponse.ok(
service.fetchData(
isAdultContentVisible = isAdultContentVisible ?: true,
contentType = contentType ?: ContentType.ALL,
member
)
)
}
@GetMapping("/popular-content-by-creator")
fun getPopularContentByCreator(
@RequestParam creatorId: Long,
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
@ -31,7 +42,8 @@ class AudioContentMainTabHomeController(private val service: AudioContentMainTab
ApiResponse.ok(
service.getPopularContentByCreator(
creatorId = creatorId,
isAdult = member.auth != null
isAdult = member.auth != null && (isAdultContentVisible ?: true),
contentType = contentType ?: ContentType.ALL
)
)
}

View File

@ -1,5 +1,6 @@
package kr.co.vividnext.sodalive.content.main.tab.home
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem
import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerService
import kr.co.vividnext.sodalive.event.EventService
@ -19,7 +20,11 @@ class AudioContentMainTabHomeService(
private val rankingService: RankingService,
private val eventService: EventService
) {
fun fetchData(member: Member): GetContentMainTabHomeResponse {
fun fetchData(
isAdultContentVisible: Boolean,
contentType: ContentType,
member: Member
): GetContentMainTabHomeResponse {
// 주간 랭킹 기간
val currentDateTime = LocalDateTime.now()
val startDate = currentDateTime
@ -37,6 +42,8 @@ class AudioContentMainTabHomeService(
val formattedLastMonday = startDate.format(startDateFormatter)
val formattedLastSunday = endDate.format(endDateFormatter)
val isAdult = member.auth != null && isAdultContentVisible
// 최근 공지사항
val latestNotice = noticeService.getLatestNotice()
@ -44,7 +51,7 @@ class AudioContentMainTabHomeService(
val contentBannerList = bannerService.getBannerList(
tabId = 1,
memberId = member.id!!,
isAdult = member.auth != null
isAdult = isAdult
)
// 인기 크리에이터
@ -56,7 +63,8 @@ class AudioContentMainTabHomeService(
// 인기 시리즈
val rankSeriesList = rankingService.getSeriesRanking(
memberId = member.id!!,
isAdult = member.auth != null,
isAdult = isAdult,
contentType = contentType,
startDate = startDate.minusDays(1),
endDate = endDate
)
@ -64,16 +72,18 @@ class AudioContentMainTabHomeService(
// 인기 콘텐츠
val rankContentList = rankingService.getContentRanking(
memberId = member.id!!,
isAdult = member.auth != null,
isAdult = isAdult,
contentType = contentType,
startDate = startDate.minusDays(1),
endDate = endDate
)
// 이벤트 배너
val eventBannerList = eventService.getEventList(isAdult = member.auth != null)
val eventBannerList = eventService.getEventList(isAdult = isAdult)
val contentRankCreatorList = rankingService.fetchCreatorBySellContentCountRankTop20(
memberId = member.id!!,
contentType = contentType,
startDate = startDate.minusDays(1),
endDate = endDate
)
@ -81,7 +91,8 @@ class AudioContentMainTabHomeService(
val salesCountRankContentList = if (contentRankCreatorList.isNotEmpty()) {
rankingService.fetchCreatorContentBySalesCountTop4(
creatorId = contentRankCreatorList[0].creatorId,
isAdult = member.auth != null
isAdult = isAdult,
contentType = contentType
)
} else {
emptyList()
@ -100,10 +111,15 @@ class AudioContentMainTabHomeService(
)
}
fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): List<GetAudioContentRankingItem> {
fun getPopularContentByCreator(
creatorId: Long,
isAdult: Boolean,
contentType: ContentType
): List<GetAudioContentRankingItem> {
return rankingService.fetchCreatorContentBySalesCountTop4(
creatorId = creatorId,
isAdult = isAdult
isAdult = isAdult,
contentType = contentType
)
}
}

View File

@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.content.main.tab.replay
import kr.co.vividnext.sodalive.common.ApiResponse
import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.member.Member
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.GetMapping
@ -14,16 +15,26 @@ import org.springframework.web.bind.annotation.RestController
class AudioContentMainTabLiveReplayController(private val service: AudioContentMainTabLiveReplayService) {
@GetMapping
fun fetchContentMainTabLiveReplay(
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(service.fetchData(member))
ApiResponse.ok(
service.fetchData(
isAdultContentVisible = isAdultContentVisible ?: true,
contentType = contentType ?: ContentType.ALL,
member
)
)
}
@GetMapping("/popular-content-by-creator")
fun getPopularContentByCreator(
@RequestParam creatorId: Long,
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
@ -31,7 +42,8 @@ class AudioContentMainTabLiveReplayController(private val service: AudioContentM
ApiResponse.ok(
service.getPopularContentByCreator(
creatorId = creatorId,
isAdult = member.auth != null
isAdult = member.auth != null && (isAdultContentVisible ?: true),
contentType = contentType ?: ContentType.ALL
)
)
}

View File

@ -21,8 +21,12 @@ class AudioContentMainTabLiveReplayService(
private val eventService: EventService,
private val curationRepository: AudioContentCurationQueryRepository
) {
fun fetchData(member: Member): GetContentMainTabLiveReplayResponse {
val isAdult = member.auth != null
fun fetchData(
isAdultContentVisible: Boolean,
contentType: ContentType,
member: Member
): GetContentMainTabLiveReplayResponse {
val isAdult = member.auth != null && isAdultContentVisible
val memberId = member.id!!
val theme = "다시듣기"
val tabId = 6L
@ -37,20 +41,23 @@ class AudioContentMainTabLiveReplayService(
memberId = memberId,
theme = listOf(theme),
isAdult = isAdult,
contentType = ContentType.ALL,
contentType = contentType,
limit = 10
)
val creatorList = repository.findCreatorByThemeContent(
memberId = memberId,
theme = theme,
minCount = 4
minCount = 4,
isAdult = isAdult,
contentType = contentType
)
val salesCountRankContentList = if (creatorList.isNotEmpty()) {
rankingService.fetchCreatorContentBySalesCountTop4(
creatorId = creatorList[0].creatorId,
isAdult = isAdult,
contentType = contentType,
theme = theme
)
} else {
@ -66,10 +73,12 @@ class AudioContentMainTabLiveReplayService(
items = contentRepository.findAudioContentByCurationIdV2(
curationId = it.id!!,
memberId = memberId,
isAdult = isAdult
isAdult = isAdult,
contentType = contentType
)
)
}
.filter { it.items.isNotEmpty() }
return GetContentMainTabLiveReplayResponse(
contentBannerList = contentBannerList,
@ -81,10 +90,15 @@ class AudioContentMainTabLiveReplayService(
)
}
fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): List<GetAudioContentRankingItem> {
fun getPopularContentByCreator(
creatorId: Long,
isAdult: Boolean,
contentType: ContentType
): List<GetAudioContentRankingItem> {
return rankingService.fetchCreatorContentBySalesCountTop4(
creatorId = creatorId,
isAdult = isAdult,
contentType = contentType,
theme = "다시듣기"
)
}

View File

@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.content.main.tab.series
import kr.co.vividnext.sodalive.common.ApiResponse
import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.member.Member
import org.springframework.data.domain.Pageable
import org.springframework.security.core.annotation.AuthenticationPrincipal
@ -15,15 +16,25 @@ import org.springframework.web.bind.annotation.RestController
class AudioContentMainTabSeriesController(private val service: AudioContentMainTabSeriesService) {
@GetMapping
fun fetchContentMainSeries(
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(service.fetchData(member))
ApiResponse.ok(
service.fetchData(
isAdultContentVisible = isAdultContentVisible ?: true,
contentType = contentType ?: ContentType.ALL,
member
)
)
}
@GetMapping("/original")
fun getOriginalAudioDramaList(
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
pageable: Pageable
) = run {
@ -32,7 +43,8 @@ class AudioContentMainTabSeriesController(private val service: AudioContentMainT
ApiResponse.ok(
service.getOriginalAudioDramaList(
memberId = member.id!!,
isAdult = member.auth != null,
isAdult = member.auth != null && (isAdultContentVisible ?: true),
contentType = contentType ?: ContentType.ALL,
offset = pageable.offset,
limit = pageable.pageSize.toLong()
)
@ -41,6 +53,8 @@ class AudioContentMainTabSeriesController(private val service: AudioContentMainT
@GetMapping("/completed-rank")
fun getRank10DaysCompletedSeriesList(
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
pageable: Pageable
) = run {
@ -49,7 +63,8 @@ class AudioContentMainTabSeriesController(private val service: AudioContentMainT
ApiResponse.ok(
service.getRank10DaysCompletedSeriesList(
memberId = member.id!!,
isAdult = member.auth != null,
isAdult = member.auth != null && (isAdultContentVisible ?: true),
contentType = contentType ?: ContentType.ALL,
offset = pageable.offset,
limit = pageable.pageSize.toLong()
)
@ -59,6 +74,8 @@ class AudioContentMainTabSeriesController(private val service: AudioContentMainT
@GetMapping("/recommend-by-genre")
fun getRecommendSeriesListByGenre(
@RequestParam genreId: Long,
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
@ -67,7 +84,8 @@ class AudioContentMainTabSeriesController(private val service: AudioContentMainT
service.getRecommendSeriesListByGenre(
genreId,
memberId = member.id!!,
isAdult = member.auth != null
isAdult = member.auth != null && (isAdultContentVisible ?: true),
contentType = contentType ?: ContentType.ALL
)
)
}
@ -75,6 +93,8 @@ class AudioContentMainTabSeriesController(private val service: AudioContentMainT
@GetMapping("/recommend-series-by-creator")
fun getRecommendSeriesByCreator(
@RequestParam creatorId: Long,
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
@ -82,7 +102,8 @@ class AudioContentMainTabSeriesController(private val service: AudioContentMainT
ApiResponse.ok(
service.getRecommendSeriesByCreator(
creatorId = creatorId,
isAdult = member.auth != null
isAdult = member.auth != null && (isAdultContentVisible ?: true),
contentType = contentType ?: ContentType.ALL
)
)
}

View File

@ -1,5 +1,6 @@
package kr.co.vividnext.sodalive.content.main.tab.series
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerService
import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationQueryRepository
import kr.co.vividnext.sodalive.content.main.tab.RecommendSeriesRepository
@ -24,8 +25,12 @@ class AudioContentMainTabSeriesService(
private val eventService: EventService,
private val curationRepository: AudioContentCurationQueryRepository
) {
fun fetchData(member: Member): GetContentMainTabSeriesResponse {
val isAdult = member.auth != null
fun fetchData(
isAdultContentVisible: Boolean,
contentType: ContentType,
member: Member
): GetContentMainTabSeriesResponse {
val isAdult = member.auth != null && isAdultContentVisible
val memberId = member.id!!
// 메인 배너 (시리즈)
@ -38,6 +43,7 @@ class AudioContentMainTabSeriesService(
val originalAudioDrama = seriesService.getOriginalAudioDramaList(
memberId = memberId,
isAdult = isAdult,
contentType = contentType,
offset = 0,
limit = 20
)
@ -55,18 +61,20 @@ class AudioContentMainTabSeriesService(
val rankSeriesList = rankingService.getSeriesRanking(
memberId = memberId,
isAdult = isAdult,
contentType = contentType,
startDate = dailyRankingStartDate,
endDate = dailyRankingEndDate
)
// 시리즈 장르
val genreList = seriesService.getGenreList(memberId = memberId, isAdult = isAdult)
val genreList = seriesService.getGenreList(memberId = memberId, isAdult = isAdult, contentType = contentType)
// 장르별 추천 시리즈
val recommendSeriesList = if (genreList.isNotEmpty()) {
rankingService.getSeriesAllRankingByGenre(
memberId = memberId,
isAdult = isAdult,
contentType = contentType,
genreId = genreList[0].id
)
} else {
@ -74,13 +82,14 @@ class AudioContentMainTabSeriesService(
}
// 새로운 시리즈
val newSeriesList = recommendSeriesRepository.getNewSeriesList(isAdult = isAdult)
val newSeriesList = recommendSeriesRepository.getNewSeriesList(isAdult = isAdult, contentType = contentType)
val (completedRankStartDate, completedRankEndDate) = calculateStartAndEndDate()
val rankCompleteSeriesList = rankingService.getCompleteSeriesRanking(
memberId = memberId,
isAdult = isAdult,
contentType = contentType,
startDate = completedRankStartDate,
endDate = completedRankEndDate
)
@ -96,6 +105,7 @@ class AudioContentMainTabSeriesService(
val seriesRankCreatorList = rankingService.fetchCreatorBySeriesRevenueRankTop20(
memberId = memberId,
contentType = contentType,
startDate = startDate.minusDays(1),
endDate = endDate
)
@ -103,7 +113,8 @@ class AudioContentMainTabSeriesService(
val salesRankContentList = if (seriesRankCreatorList.isNotEmpty()) {
rankingService.fetchCreatorSeriesBySales(
creatorId = seriesRankCreatorList[0].creatorId,
isAdult = isAdult
isAdult = isAdult,
contentType = contentType
)
} else {
emptyList()
@ -120,7 +131,8 @@ class AudioContentMainTabSeriesService(
items = seriesService.fetchSeriesByCurationId(
curationId = it.id!!,
memberId = memberId,
isAdult = isAdult
isAdult = isAdult,
contentType = contentType
)
)
}
@ -148,13 +160,15 @@ class AudioContentMainTabSeriesService(
fun getOriginalAudioDramaList(
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
offset: Long,
limit: Long
): GetSeriesListResponse {
val totalCount = seriesService.getOriginalAudioDramaTotalCount(memberId, isAdult)
val totalCount = seriesService.getOriginalAudioDramaTotalCount(memberId, isAdult, contentType)
val items = seriesService.getOriginalAudioDramaList(
memberId = memberId,
isAdult = isAdult,
contentType = contentType,
offset = offset,
limit = limit
)
@ -165,6 +179,7 @@ class AudioContentMainTabSeriesService(
fun getRank10DaysCompletedSeriesList(
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
offset: Long,
limit: Long
): GetSeriesListResponse {
@ -172,12 +187,14 @@ class AudioContentMainTabSeriesService(
val totalCount = rankingService.getCompleteSeriesRankingTotalCount(
memberId = memberId,
isAdult = isAdult
isAdult = isAdult,
contentType = contentType
)
val items = rankingService.getCompleteSeriesRanking(
memberId = memberId,
isAdult = isAdult,
contentType = contentType,
startDate = startDate,
endDate = endDate,
offset = offset,
@ -190,19 +207,26 @@ class AudioContentMainTabSeriesService(
fun getRecommendSeriesListByGenre(
genreId: Long,
memberId: Long,
isAdult: Boolean
isAdult: Boolean,
contentType: ContentType
): List<GetSeriesListResponse.SeriesListItem> {
return rankingService.getSeriesAllRankingByGenre(
memberId = memberId,
isAdult = isAdult,
contentType = contentType,
genreId = genreId
)
}
fun getRecommendSeriesByCreator(creatorId: Long, isAdult: Boolean): List<GetSeriesListResponse.SeriesListItem> {
fun getRecommendSeriesByCreator(
creatorId: Long,
isAdult: Boolean,
contentType: ContentType
): List<GetSeriesListResponse.SeriesListItem> {
return rankingService.fetchCreatorSeriesBySales(
creatorId = creatorId,
isAdult = isAdult
isAdult = isAdult,
contentType = contentType
)
}

View File

@ -35,10 +35,17 @@ interface ContentSeriesQueryRepository {
fun getKeywordList(seriesId: Long): List<String>
fun getSeriesContentMinMaxPrice(seriesId: Long): GetSeriesContentMinMaxPriceResponse
fun getRecommendSeriesList(isAuth: Boolean, contentType: ContentType, limit: Long): List<Series>
fun getOriginalAudioDramaList(memberId: Long, isAdult: Boolean, offset: Long = 0, limit: Long = 20): List<Series>
fun getOriginalAudioDramaTotalCount(memberId: Long, isAdult: Boolean): Int
fun getGenreList(isAdult: Boolean, memberId: Long): List<GetSeriesGenreListResponse>
fun findByCurationId(curationId: Long, memberId: Long, isAdult: Boolean): List<Series>
fun getOriginalAudioDramaList(
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
offset: Long = 0,
limit: Long = 20
): List<Series>
fun getOriginalAudioDramaTotalCount(memberId: Long, isAdult: Boolean, contentType: ContentType): Int
fun getGenreList(isAdult: Boolean, memberId: Long, contentType: ContentType): List<GetSeriesGenreListResponse>
fun findByCurationId(curationId: Long, memberId: Long, isAdult: Boolean, contentType: ContentType): List<Series>
}
class ContentSeriesQueryRepositoryImpl(
@ -130,7 +137,15 @@ class ContentSeriesQueryRepositoryImpl(
} else {
if (contentType != ContentType.ALL) {
where = where.and(
series.member.auth.gender.eq(if (contentType == ContentType.MALE) 0 else 1)
series.member.isNull.or(
series.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
@ -144,7 +159,13 @@ class ContentSeriesQueryRepositoryImpl(
.fetch()
}
override fun getOriginalAudioDramaList(memberId: Long, isAdult: Boolean, offset: Long, limit: Long): List<Series> {
override fun getOriginalAudioDramaList(
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
offset: Long,
limit: Long
): List<Series> {
val blockMemberCondition = blockMember.member.id.eq(member.id)
.and(blockMember.isActive.isTrue)
.and(blockMember.blockedMember.id.eq(memberId))
@ -155,6 +176,20 @@ class ContentSeriesQueryRepositoryImpl(
if (!isAdult) {
where = where.and(series.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
series.member.isNull.or(
series.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory
@ -168,7 +203,7 @@ class ContentSeriesQueryRepositoryImpl(
.fetch()
}
override fun getOriginalAudioDramaTotalCount(memberId: Long, isAdult: Boolean): Int {
override fun getOriginalAudioDramaTotalCount(memberId: Long, isAdult: Boolean, contentType: ContentType): Int {
val blockMemberCondition = blockMember.member.id.eq(member.id)
.and(blockMember.isActive.isTrue)
.and(blockMember.blockedMember.id.eq(memberId))
@ -179,6 +214,20 @@ class ContentSeriesQueryRepositoryImpl(
if (!isAdult) {
where = where.and(series.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
series.member.isNull.or(
series.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory
@ -191,7 +240,11 @@ class ContentSeriesQueryRepositoryImpl(
.size
}
override fun getGenreList(isAdult: Boolean, memberId: Long): List<GetSeriesGenreListResponse> {
override fun getGenreList(
isAdult: Boolean,
memberId: Long,
contentType: ContentType
): List<GetSeriesGenreListResponse> {
val blockMemberCondition = blockMember.member.id.eq(member.id)
.and(blockMember.isActive.isTrue)
.and(blockMember.blockedMember.id.eq(memberId))
@ -209,6 +262,20 @@ class ContentSeriesQueryRepositoryImpl(
if (!isAdult) {
where = where.and(seriesGenre.isAdult.isFalse)
.and(series.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
series.member.isNull.or(
series.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory
@ -225,7 +292,12 @@ class ContentSeriesQueryRepositoryImpl(
.fetch()
}
override fun findByCurationId(curationId: Long, memberId: Long, isAdult: Boolean): List<Series> {
override fun findByCurationId(
curationId: Long,
memberId: Long,
isAdult: Boolean,
contentType: ContentType
): List<Series> {
val blockMemberCondition = blockMember.member.id.eq(member.id)
.and(blockMember.isActive.isTrue)
.and(blockMember.blockedMember.id.eq(memberId))
@ -239,6 +311,20 @@ class ContentSeriesQueryRepositoryImpl(
if (!isAdult) {
where = where.and(series.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
series.member.isNull.or(
series.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory

View File

@ -30,22 +30,23 @@ class ContentSeriesService(
@Value("\${cloud.aws.cloud-front.host}")
private val coverImageHost: String
) {
fun getOriginalAudioDramaTotalCount(memberId: Long, isAdult: Boolean): Int {
return repository.getOriginalAudioDramaTotalCount(memberId, isAdult)
fun getOriginalAudioDramaTotalCount(memberId: Long, isAdult: Boolean, contentType: ContentType): Int {
return repository.getOriginalAudioDramaTotalCount(memberId, isAdult, contentType)
}
fun getOriginalAudioDramaList(
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
offset: Long = 0,
limit: Long = 20
): List<GetSeriesListResponse.SeriesListItem> {
val originalAudioDramaList = repository.getOriginalAudioDramaList(memberId, isAdult, offset, limit)
val originalAudioDramaList = repository.getOriginalAudioDramaList(memberId, isAdult, contentType, offset, limit)
return seriesToSeriesListItem(originalAudioDramaList, isAdult)
}
fun getGenreList(memberId: Long, isAdult: Boolean): List<GetSeriesGenreListResponse> {
return repository.getGenreList(memberId = memberId, isAdult = isAdult)
fun getGenreList(memberId: Long, isAdult: Boolean, contentType: ContentType): List<GetSeriesGenreListResponse> {
return repository.getGenreList(memberId = memberId, isAdult = isAdult, contentType = contentType)
}
fun getSeriesList(
@ -191,9 +192,15 @@ class ContentSeriesService(
fun fetchSeriesByCurationId(
curationId: Long,
memberId: Long,
isAdult: Boolean
isAdult: Boolean,
contentType: ContentType
): List<GetSeriesListResponse.SeriesListItem> {
val seriesList = repository.findByCurationId(curationId = curationId, memberId = memberId, isAdult = isAdult)
val seriesList = repository.findByCurationId(
curationId = curationId,
memberId = memberId,
isAdult = isAdult,
contentType = contentType
)
return seriesToSeriesListItem(seriesList, isAdult)
}

View File

@ -1,8 +1,10 @@
package kr.co.vividnext.sodalive.content.theme
import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
import kr.co.vividnext.sodalive.content.theme.QAudioContentTheme.audioContentTheme
import kr.co.vividnext.sodalive.member.QMember.member
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Repository
@ -27,12 +29,30 @@ class AudioContentThemeQueryRepository(
.fetch()
}
fun getActiveThemeOfContent(isAdult: Boolean = false, isFree: Boolean = false): List<String> {
fun getActiveThemeOfContent(
isAdult: Boolean = false,
isFree: Boolean = false,
contentType: ContentType
): List<String> {
var where = audioContent.isActive.isTrue
.and(audioContentTheme.isActive.isTrue)
if (!isAdult) {
where = where.and(audioContent.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
where = if (isFree) {
@ -44,6 +64,7 @@ class AudioContentThemeQueryRepository(
return queryFactory
.select(audioContentTheme.theme)
.from(audioContent)
.innerJoin(audioContent.member, member)
.innerJoin(audioContent.theme, audioContentTheme)
.where(where)
.groupBy(audioContentTheme.id)

View File

@ -3,6 +3,7 @@ package kr.co.vividnext.sodalive.rank
import com.querydsl.core.types.dsl.Expressions
import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.admin.content.series.genre.QSeriesGenre.seriesGenre
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
import kr.co.vividnext.sodalive.content.comment.QAudioContentComment.audioContentComment
import kr.co.vividnext.sodalive.content.like.QAudioContentLike.audioContentLike
@ -44,6 +45,7 @@ class RankingRepository(
fun getAudioContentRanking(
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
startDate: LocalDateTime,
endDate: LocalDateTime,
offset: Long,
@ -66,6 +68,20 @@ class RankingRepository(
if (!isAdult) {
where = where.and(audioContent.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
if (theme.isNotBlank()) {
@ -167,6 +183,7 @@ class RankingRepository(
fun getSeriesRanking(
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
startDate: LocalDateTime,
endDate: LocalDateTime
): List<Series> {
@ -188,6 +205,20 @@ class RankingRepository(
if (!isAdult) {
where = where.and(series.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
series.member.isNull.or(
series.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory
@ -209,7 +240,7 @@ class RankingRepository(
.fetch()
}
fun getCompleteSeriesRankingTotalCount(memberId: Long, isAdult: Boolean): Int {
fun getCompleteSeriesRankingTotalCount(memberId: Long, isAdult: Boolean, contentType: ContentType): Int {
val blockMemberCondition = blockMember.member.id.eq(member.id)
.and(blockMember.isActive.isTrue)
.and(blockMember.blockedMember.id.eq(memberId))
@ -226,6 +257,20 @@ class RankingRepository(
if (!isAdult) {
where = where.and(series.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
series.member.isNull.or(
series.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory
@ -244,6 +289,7 @@ class RankingRepository(
fun getCompleteSeriesRanking(
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
startDate: LocalDateTime,
endDate: LocalDateTime,
offset: Long,
@ -270,6 +316,20 @@ class RankingRepository(
if (!isAdult) {
where = where.and(series.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
series.member.isNull.or(
series.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory
@ -288,7 +348,12 @@ class RankingRepository(
.fetch()
}
fun getSeriesAllRankingByGenre(memberId: Long, isAdult: Boolean, genreId: Long): List<Series> {
fun getSeriesAllRankingByGenre(
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
genreId: Long
): List<Series> {
val blockMemberCondition = blockMember.member.id.eq(member.id)
.and(blockMember.isActive.isTrue)
.and(blockMember.blockedMember.id.eq(memberId))
@ -306,6 +371,20 @@ class RankingRepository(
if (!isAdult) {
where = where.and(series.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
series.member.isNull.or(
series.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory
@ -330,6 +409,7 @@ class RankingRepository(
fun fetchCreatorBySellContentCountRankTop20(
memberId: Long,
contentType: ContentType,
startDate: LocalDateTime,
endDate: LocalDateTime
): List<ContentCreatorResponse> {
@ -342,16 +422,30 @@ class RankingRepository(
.and(order.createdAt.goe(startDate))
.and(order.createdAt.lt(endDate))
val memberCondition = member.isActive.isTrue
var memberCondition = member.isActive.isTrue
.and(member.role.eq(MemberRole.CREATOR))
.and(member.id.eq(audioContent.member.id))
val where = audioContent.isActive.isTrue
var where = audioContent.isActive.isTrue
.and(audioContent.price.gt(0))
.and(audioContent.duration.isNotNull)
.and(audioContent.limited.isNull)
.and(blockMember.id.isNull)
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.auth.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
return queryFactory
.select(
QContentCreatorResponse(
@ -376,6 +470,7 @@ class RankingRepository(
fun fetchCreatorContentBySalesCountTop4(
creatorId: Long,
isAdult: Boolean,
contentType: ContentType,
theme: String
): List<GetAudioContentRankingItem> {
var where = member.isActive.isTrue
@ -389,6 +484,20 @@ class RankingRepository(
if (!isAdult) {
where = where.and(audioContent.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
if (theme.isNotBlank()) {
@ -423,6 +532,7 @@ class RankingRepository(
fun fetchCreatorBySeriesRevenueRankTop20(
memberId: Long,
contentType: ContentType,
startDate: LocalDateTime,
endDate: LocalDateTime
): List<ContentCreatorResponse> {
@ -435,7 +545,7 @@ class RankingRepository(
.and(order.createdAt.goe(startDate))
.and(order.createdAt.lt(startDate))
val where = member.isActive.isTrue
var where = member.isActive.isTrue
.and(member.role.eq(MemberRole.CREATOR))
.and(series.isActive.isTrue)
.and(audioContent.isActive.isTrue)
@ -443,6 +553,20 @@ class RankingRepository(
.and(audioContent.limited.isNull)
.and(blockMember.id.isNull)
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
return queryFactory
.select(
QContentCreatorResponse(
@ -469,7 +593,7 @@ class RankingRepository(
.fetch()
}
fun fetchCreatorSeriesBySales(creatorId: Long, isAdult: Boolean): List<Series> {
fun fetchCreatorSeriesBySales(creatorId: Long, isAdult: Boolean, contentType: ContentType): List<Series> {
var where = member.isActive.isTrue
.and(member.role.eq(MemberRole.CREATOR))
.and(series.isActive.isTrue)
@ -481,6 +605,20 @@ class RankingRepository(
if (!isAdult) {
where = where.and(series.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
series.member.isNull.or(
series.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory
@ -501,7 +639,11 @@ class RankingRepository(
.fetch()
}
fun fetchFreeContentByCreatorIdTop4(creatorId: Long, isAdult: Boolean): List<GetAudioContentRankingItem> {
fun fetchFreeContentByCreatorIdTop4(
creatorId: Long,
isAdult: Boolean,
contentType: ContentType
): List<GetAudioContentRankingItem> {
var where = member.isActive.isTrue
.and(member.id.eq(creatorId))
.and(member.role.eq(MemberRole.CREATOR))
@ -512,6 +654,20 @@ class RankingRepository(
if (!isAdult) {
where = where.and(audioContent.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory
@ -538,7 +694,11 @@ class RankingRepository(
.fetch()
}
fun fetchCreatorContentByLikeCountTop4(creatorId: Long, isAdult: Boolean): List<GetAudioContentRankingItem> {
fun fetchCreatorContentByLikeCountTop4(
creatorId: Long,
isAdult: Boolean,
contentType: ContentType
): List<GetAudioContentRankingItem> {
var where = member.isActive.isTrue
.and(member.id.eq(creatorId))
.and(member.role.eq(MemberRole.CREATOR))
@ -550,6 +710,20 @@ class RankingRepository(
if (!isAdult) {
where = where.and(audioContent.isAdult.isFalse)
} else {
if (contentType != ContentType.ALL) {
where = where.and(
audioContent.member.isNull.or(
audioContent.member.auth.gender.eq(
if (contentType == ContentType.MALE) {
0
} else {
1
}
)
)
)
}
}
return queryFactory

View File

@ -1,5 +1,6 @@
package kr.co.vividnext.sodalive.rank
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.content.main.ContentCreatorResponse
import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem
import kr.co.vividnext.sodalive.content.series.GetSeriesListResponse
@ -40,6 +41,7 @@ class RankingService(
fun getContentRanking(
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
startDate: LocalDateTime,
endDate: LocalDateTime,
offset: Long = 0,
@ -50,6 +52,7 @@ class RankingService(
return repository.getAudioContentRanking(
memberId = memberId,
isAdult = isAdult,
contentType = contentType,
startDate = startDate,
endDate = endDate,
offset = offset,
@ -62,21 +65,24 @@ class RankingService(
fun getSeriesRanking(
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
startDate: LocalDateTime,
endDate: LocalDateTime
): List<GetSeriesListResponse.SeriesListItem> {
val seriesList = repository.getSeriesRanking(memberId, isAdult, startDate, endDate)
val seriesList = repository.getSeriesRanking(memberId, isAdult, contentType, startDate, endDate)
return seriesToSeriesListItem(seriesList = seriesList, isAdult = isAdult)
}
fun getSeriesAllRankingByGenre(
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
genreId: Long
): List<GetSeriesListResponse.SeriesListItem> {
val seriesList = repository.getSeriesAllRankingByGenre(
memberId = memberId,
isAdult = isAdult,
contentType = contentType,
genreId = genreId
)
return seriesToSeriesListItem(seriesList = seriesList, isAdult = isAdult)
@ -84,17 +90,20 @@ class RankingService(
fun getCompleteSeriesRankingTotalCount(
memberId: Long,
isAdult: Boolean
isAdult: Boolean,
contentType: ContentType
): Int {
return repository.getCompleteSeriesRankingTotalCount(
memberId = memberId,
isAdult = isAdult
isAdult = isAdult,
contentType = contentType
)
}
fun getCompleteSeriesRanking(
memberId: Long,
isAdult: Boolean,
contentType: ContentType,
startDate: LocalDateTime,
endDate: LocalDateTime,
offset: Long = 0,
@ -103,6 +112,7 @@ class RankingService(
val seriesList = repository.getCompleteSeriesRanking(
memberId = memberId,
isAdult = isAdult,
contentType = contentType,
startDate = startDate,
endDate = endDate,
offset = offset,
@ -179,38 +189,57 @@ class RankingService(
fun fetchCreatorBySellContentCountRankTop20(
memberId: Long,
contentType: ContentType,
startDate: LocalDateTime,
endDate: LocalDateTime
): List<ContentCreatorResponse> {
return repository.fetchCreatorBySellContentCountRankTop20(memberId, startDate, endDate)
return repository.fetchCreatorBySellContentCountRankTop20(memberId, contentType, startDate, endDate)
}
fun fetchCreatorContentBySalesCountTop4(
creatorId: Long,
isAdult: Boolean,
contentType: ContentType,
theme: String = ""
): List<GetAudioContentRankingItem> {
return repository.fetchCreatorContentBySalesCountTop4(creatorId, isAdult, theme)
return repository.fetchCreatorContentBySalesCountTop4(creatorId, isAdult, contentType, theme)
}
fun fetchCreatorContentByLikeCountTop4(creatorId: Long, isAdult: Boolean): List<GetAudioContentRankingItem> {
return repository.fetchCreatorContentByLikeCountTop4(creatorId, isAdult)
fun fetchCreatorContentByLikeCountTop4(
creatorId: Long,
isAdult: Boolean,
contentType: ContentType
): List<GetAudioContentRankingItem> {
return repository.fetchCreatorContentByLikeCountTop4(creatorId, isAdult, contentType)
}
fun fetchCreatorBySeriesRevenueRankTop20(
memberId: Long,
contentType: ContentType,
startDate: LocalDateTime,
endDate: LocalDateTime
): List<ContentCreatorResponse> {
return repository.fetchCreatorBySeriesRevenueRankTop20(memberId, startDate, endDate)
return repository.fetchCreatorBySeriesRevenueRankTop20(memberId, contentType, startDate, endDate)
}
fun fetchCreatorSeriesBySales(creatorId: Long, isAdult: Boolean): List<GetSeriesListResponse.SeriesListItem> {
val seriesList = repository.fetchCreatorSeriesBySales(creatorId = creatorId, isAdult = isAdult)
fun fetchCreatorSeriesBySales(
creatorId: Long,
isAdult: Boolean,
contentType: ContentType
): List<GetSeriesListResponse.SeriesListItem> {
val seriesList = repository.fetchCreatorSeriesBySales(
creatorId = creatorId,
isAdult = isAdult,
contentType = contentType
)
return seriesToSeriesListItem(seriesList, isAdult)
}
fun fetchFreeContentByCreatorIdTop4(creatorId: Long, isAdult: Boolean): List<GetAudioContentRankingItem> {
return repository.fetchFreeContentByCreatorIdTop4(creatorId, isAdult)
fun fetchFreeContentByCreatorIdTop4(
creatorId: Long,
isAdult: Boolean,
contentType: ContentType
): List<GetAudioContentRankingItem> {
return repository.fetchFreeContentByCreatorIdTop4(creatorId, isAdult, contentType)
}
}