diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt index d758d01..245792e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt @@ -24,6 +24,7 @@ import kr.co.vividnext.sodalive.content.theme.QAudioContentTheme.audioContentThe import kr.co.vividnext.sodalive.event.QEvent.event import kr.co.vividnext.sodalive.member.MemberRole import kr.co.vividnext.sodalive.member.QMember.member +import kr.co.vividnext.sodalive.member.block.QBlockMember.blockMember import org.springframework.beans.factory.annotation.Value import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository @@ -61,7 +62,6 @@ interface AudioContentQueryRepository { ): List fun findByTheme( - cloudfrontHost: String, memberId: Long, theme: String = "", sortType: SortType = SortType.NEWEST, @@ -334,7 +334,6 @@ class AudioContentQueryRepositoryImpl( } override fun findByTheme( - cloudfrontHost: String, memberId: Long, theme: String, sortType: SortType, @@ -343,6 +342,10 @@ class AudioContentQueryRepositoryImpl( offset: Long, limit: Long ): List { + val blockMemberCondition = blockMember.member.id.eq(member.id) + .and(blockMember.isActive.isTrue) + .and(blockMember.blockedMember.id.eq(memberId)) + val orderBy = when (sortType) { SortType.NEWEST -> listOf(audioContent.releaseDate.desc(), audioContent.id.desc()) SortType.PRICE_HIGH -> listOf( @@ -365,6 +368,7 @@ class AudioContentQueryRepositoryImpl( .or(audioContent.releaseDate.loe(LocalDateTime.now())) .or(audioContent.member.id.eq(memberId)) ) + .and(blockMember.id.isNull) if (!isAdult) { where = where.and(audioContent.isAdult.isFalse) @@ -384,10 +388,10 @@ class AudioContentQueryRepositoryImpl( .select( QGetAudioContentMainItem( audioContent.id, - audioContent.coverImage.prepend("/").prepend(cloudfrontHost), + audioContent.coverImage.prepend("/").prepend(imageHost), audioContent.title, member.id, - member.profileImage.prepend("/").prepend(cloudfrontHost), + member.profileImage.prepend("/").prepend(imageHost), member.nickname, audioContent.price, audioContent.duration @@ -396,6 +400,7 @@ class AudioContentQueryRepositoryImpl( .from(audioContent) .innerJoin(audioContent.member, member) .innerJoin(audioContent.theme, audioContentTheme) + .leftJoin(blockMember).on(blockMemberCondition) .where(where) .offset(offset) .limit(limit) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt index 2963ec5..8f03d29 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt @@ -39,7 +39,6 @@ class AudioContentMainService( pageable: Pageable ): List { return repository.findByTheme( - cloudfrontHost = imageHost, memberId = member.id!!, theme = theme, isAdult = member.auth != null && isAdultContentVisible, @@ -47,7 +46,6 @@ class AudioContentMainService( offset = pageable.offset, limit = pageable.pageSize.toLong() ) - .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) } } @Transactional(readOnly = true) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentController.kt new file mode 100644 index 0000000..80762a1 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentController.kt @@ -0,0 +1,22 @@ +package kr.co.vividnext.sodalive.content.main.tab.content + +import kr.co.vividnext.sodalive.common.ApiResponse +import kr.co.vividnext.sodalive.common.SodaException +import kr.co.vividnext.sodalive.member.Member +import org.springframework.security.core.annotation.AuthenticationPrincipal +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/v2/audio-content/main/content") +class AudioContentMainTabContentController(private val service: AudioContentMainTabContentService) { + @GetMapping + fun fetchContentMainTabContent( + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok(service.fetchData(member)) + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt new file mode 100644 index 0000000..182ae7c --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/AudioContentMainTabContentService.kt @@ -0,0 +1,110 @@ +package kr.co.vividnext.sodalive.content.main.tab.content + +import kr.co.vividnext.sodalive.content.AudioContentRepository +import kr.co.vividnext.sodalive.content.ContentType +import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerService +import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository +import kr.co.vividnext.sodalive.event.EventService +import kr.co.vividnext.sodalive.member.Member +import kr.co.vividnext.sodalive.rank.RankingService +import org.springframework.stereotype.Service +import java.time.LocalDateTime + +@Service +class AudioContentMainTabContentService( + private val bannerService: AudioContentBannerService, + private val audioContentRepository: AudioContentRepository, + private val audioContentThemeRepository: AudioContentThemeQueryRepository, + private val rankingService: RankingService, + private val eventService: EventService +) { + fun fetchData(member: Member): GetContentMainTabContentResponse { + /** + * 새로운 단편 + * 일간 랭킹 + * 채널별 추천 단편 + */ + val memberId = member.id!! + val isAdult = member.auth != null + + // 단편 배너 + val contentBannerList = bannerService.getBannerList( + tabId = 3, + memberId = memberId, + isAdult = isAdult + ) + + // 새로운 단편 테마 + val themeOfContentList = audioContentThemeRepository.getActiveThemeOfContent(isAdult = isAdult) + + // 새로운 단편 + val newContentList = if (themeOfContentList.isNotEmpty()) { + audioContentRepository.findByTheme( + memberId = member.id!!, + theme = themeOfContentList[0], + isAdult = member.auth != null, + contentType = ContentType.ALL, + offset = 0, + limit = 10 + ) + } else { + emptyList() + } + + // 일간 랭킹 + val currentDateTime = LocalDateTime.now() + val dailyRankingStartDate = currentDateTime + .withHour(15) + .withMinute(0) + .withSecond(0) + .minusDays(2) + val dailyRankingEndDate = dailyRankingStartDate + .plusDays(1) + + val rankContentList = rankingService.getContentRanking( + memberId = memberId, + isAdult = isAdult, + startDate = dailyRankingStartDate, + endDate = dailyRankingEndDate + ) + + // 이벤트 배너 + val eventBannerList = eventService.getEventList(isAdult = isAdult) + + val contentRankCreatorList = rankingService.fetchCreatorByContentRevenueRankTop20( + memberId = member.id!!, + startDate = dailyRankingStartDate.minusDays(1), + endDate = dailyRankingEndDate + ) + + val salesRankContentList = if (contentRankCreatorList.isNotEmpty()) { + rankingService.fetchCreatorContentBySalesTop2( + creatorId = contentRankCreatorList[0].creatorId, + isAdult = member.auth != null + ) + } else { + emptyList() + } + + val salesCountRankContentList = if (contentRankCreatorList.isNotEmpty()) { + rankingService.fetchCreatorContentBySalesCountTop2( + creatorId = contentRankCreatorList[0].creatorId, + isAdult = member.auth != null + ) + } else { + emptyList() + } + + return GetContentMainTabContentResponse( + bannerList = contentBannerList, + contentThemeList = themeOfContentList, + newContentList = newContentList, + rankSortTypeList = listOf("매출", "댓글", "좋아요"), + rankContentList = rankContentList, + contentRankCreatorList = contentRankCreatorList, + salesRankContentList = salesRankContentList, + salesCountRankContentList = salesCountRankContentList, + eventBannerList = eventBannerList + ) + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/GetContentMainTabContentResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/GetContentMainTabContentResponse.kt new file mode 100644 index 0000000..721e960 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/content/GetContentMainTabContentResponse.kt @@ -0,0 +1,20 @@ +package kr.co.vividnext.sodalive.content.main.tab.content + +import kr.co.vividnext.sodalive.content.main.ContentCreatorResponse +import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem +import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem +import kr.co.vividnext.sodalive.content.main.banner.GetAudioContentBannerResponse +import kr.co.vividnext.sodalive.event.GetEventResponse + +data class GetContentMainTabContentResponse( + val tabId: Long = 3, + val bannerList: List, + val contentThemeList: List, + val newContentList: List, + val rankSortTypeList: List, + val rankContentList: List, + val contentRankCreatorList: List, + val salesRankContentList: List, + val salesCountRankContentList: List, + val eventBannerList: GetEventResponse +) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/theme/AudioContentThemeService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/theme/AudioContentThemeService.kt index 5a3c6a9..b0ad97a 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/theme/AudioContentThemeService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/theme/AudioContentThemeService.kt @@ -6,19 +6,13 @@ import kr.co.vividnext.sodalive.content.ContentType import kr.co.vividnext.sodalive.content.SortType import kr.co.vividnext.sodalive.content.theme.content.GetContentByThemeResponse 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 @Service class AudioContentThemeService( private val queryRepository: AudioContentThemeQueryRepository, - private val blockMemberRepository: BlockMemberRepository, - private val contentRepository: AudioContentRepository, - - @Value("\${cloud.aws.cloud-front.host}") - private val imageHost: String + private val contentRepository: AudioContentRepository ) { @Transactional(readOnly = true) fun getThemes(): List { @@ -46,7 +40,6 @@ class AudioContentThemeService( ) val items = contentRepository.findByTheme( - cloudfrontHost = imageHost, memberId = member.id!!, theme = theme.theme, sortType = sortType, @@ -55,9 +48,6 @@ class AudioContentThemeService( offset = offset, limit = limit ) - .asSequence() - .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) } - .toList() return GetContentByThemeResponse( theme = theme.theme,