diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesController.kt index 13cdc3a..5811af9 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesController.kt @@ -64,4 +64,13 @@ class ContentSeriesController(private val service: ContentSeriesService) { ) ) } + + @GetMapping("/recommend") + fun getRecommendSeriesList( + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok(service.getRecommendSeriesList(member = member)) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesRepository.kt index cc763bc..cae0c84 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesRepository.kt @@ -1,5 +1,6 @@ package kr.co.vividnext.sodalive.content.series +import com.querydsl.core.types.dsl.Expressions import com.querydsl.jpa.impl.JPAQueryFactory import kr.co.vividnext.sodalive.content.QAudioContent.audioContent import kr.co.vividnext.sodalive.content.hashtag.QHashTag.hashTag @@ -26,6 +27,7 @@ interface ContentSeriesQueryRepository { fun getSeriesDetail(seriesId: Long, isAuth: Boolean): Series? fun getKeywordList(seriesId: Long): List fun getSeriesContentMinMaxPrice(seriesId: Long): GetSeriesContentMinMaxPriceResponse + fun getRecommendSeriesList(memberId: Long, isAuth: Boolean, limit: Long): List } class ContentSeriesQueryRepositoryImpl( @@ -108,4 +110,20 @@ class ContentSeriesQueryRepositoryImpl( .where(series.id.eq(seriesId)) .fetchFirst() } + + override fun getRecommendSeriesList(memberId: Long, isAuth: Boolean, limit: Long): List { + var where = series.isActive.isTrue + + if (!isAuth) { + where = where.and(series.isAdult.isFalse) + } + + return queryFactory + .selectFrom(series) + .where(where) + .orderBy(Expressions.numberTemplate(Double::class.java, "function('rand')").asc()) + .offset(0) + .limit(limit) + .fetch() + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesService.kt index 27fe4fb..1cefd7c 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/series/ContentSeriesService.kt @@ -5,11 +5,13 @@ import kr.co.vividnext.sodalive.content.order.OrderRepository import kr.co.vividnext.sodalive.content.order.OrderType import kr.co.vividnext.sodalive.content.series.content.ContentSeriesContentRepository import kr.co.vividnext.sodalive.content.series.content.GetSeriesContentListResponse +import kr.co.vividnext.sodalive.creator.admin.content.series.Series import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesPublishedDaysOfWeek import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesSortType import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesState import kr.co.vividnext.sodalive.explorer.ExplorerQueryRepository 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 java.time.LocalDateTime @@ -20,6 +22,7 @@ import java.time.format.DateTimeFormatter class ContentSeriesService( private val repository: ContentSeriesRepository, private val orderRepository: OrderRepository, + private val blockMemberRepository: BlockMemberRepository, private val explorerQueryRepository: ExplorerQueryRepository, private val seriesContentRepository: ContentSeriesContentRepository, @@ -40,43 +43,9 @@ class ContentSeriesService( isAuth = member.auth != null, offset = offset, limit = limit - ) + ).filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.member!!.id!!) } - val items = rawItems - .map { - GetSeriesListResponse.SeriesListItem( - seriesId = it.id!!, - title = it.title, - coverImage = "$coverImageHost/${it.coverImage!!}", - publishedDaysOfWeek = publishedDaysOfWeekText(it.publishedDaysOfWeek), - isComplete = it.state == SeriesState.COMPLETE, - creator = GetSeriesListResponse.SeriesListItemCreator( - creatorId = it.member!!.id!!, - nickname = it.member!!.nickname, - profileImage = "$coverImageHost/${it.member!!.profileImage!!}" - ) - ) - } - .map { - it.numberOfContent = seriesContentRepository.getContentCount( - seriesId = it.seriesId, - isAdult = member.auth != null - ) - - it - } - .map { - val nowDateTime = LocalDateTime.now() - - it.isNew = seriesContentRepository.isNewContent( - seriesId = it.seriesId, - isAdult = member.auth == null, - fromDate = nowDateTime.minusDays(7), - nowDate = nowDateTime - ) - - it - } + val items = seriesToSeriesListItem(seriesList = rawItems, isAdult = member.auth != null) return GetSeriesListResponse(totalCount, items) } @@ -87,6 +56,11 @@ class ContentSeriesService( isAuth = member.auth != null ) ?: throw SodaException("잘못된 시리즈 입니다.\n다시 시도해 주세요") + val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = series.member!!.id!!) + if (isBlocked) { + throw SodaException("잘못된 시리즈 입니다.\n다시 시도해 주세요") + } + val isFollow = explorerQueryRepository.isFollow( creatorId = series.member!!.id!!, memberId = member.id!! @@ -167,6 +141,57 @@ class ContentSeriesService( return GetSeriesContentListResponse(totalCount, contentList) } + fun getRecommendSeriesList(member: Member): List { + val seriesList = repository.getRecommendSeriesList( + memberId = member.id!!, + isAuth = member.auth != null, + limit = 10 + ).filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.member!!.id!!) } + + return seriesToSeriesListItem(seriesList = seriesList, isAdult = member.auth != null) + } + + private fun seriesToSeriesListItem( + seriesList: List, + isAdult: Boolean + ): List { + return seriesList + .map { + GetSeriesListResponse.SeriesListItem( + seriesId = it.id!!, + title = it.title, + coverImage = "$coverImageHost/${it.coverImage!!}", + publishedDaysOfWeek = publishedDaysOfWeekText(it.publishedDaysOfWeek), + isComplete = it.state == SeriesState.COMPLETE, + creator = GetSeriesListResponse.SeriesListItemCreator( + creatorId = it.member!!.id!!, + nickname = it.member!!.nickname, + profileImage = "$coverImageHost/${it.member!!.profileImage!!}" + ) + ) + } + .map { + it.numberOfContent = seriesContentRepository.getContentCount( + seriesId = it.seriesId, + isAdult = isAdult + ) + + it + } + .map { + val nowDateTime = LocalDateTime.now() + + it.isNew = seriesContentRepository.isNewContent( + seriesId = it.seriesId, + isAdult = isAdult, + fromDate = nowDateTime.minusDays(7), + nowDate = nowDateTime + ) + + it + } + } + private fun publishedDaysOfWeekText(publishedDaysOfWeek: Set): String { val dayOfWeekText = publishedDaysOfWeek.toList().sortedBy { it.ordinal } .map {