From 8fb124727961c35370c7fec90678684be573be98 Mon Sep 17 00:00:00 2001 From: Klaus Date: Sun, 9 Feb 2025 22:54:45 +0900 Subject: [PATCH 01/26] =?UTF-8?q?=EA=B3=B5=EC=A7=80=EC=82=AC=ED=95=AD=20-?= =?UTF-8?q?=20QueryProjection=20=EC=82=AC=EC=9A=A9=20-=20QueryDSL=EC=9D=84?= =?UTF-8?q?=20=ED=86=B5=ED=95=B4=20DTO=EB=A1=9C=20=EB=B0=94=EB=A1=9C=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tab/home/GetContentMainTabHomeResponse.kt | 4 +- .../sodalive/notice/GetNoticeResponse.kt | 7 +--- .../sodalive/notice/ServiceNoticeService.kt | 18 +------- .../notice/ServiceServiceNoticeRepository.kt | 42 +++++++++++++++---- 4 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/GetContentMainTabHomeResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/GetContentMainTabHomeResponse.kt index c104a77..db9b01f 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/GetContentMainTabHomeResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/GetContentMainTabHomeResponse.kt @@ -6,11 +6,11 @@ import kr.co.vividnext.sodalive.content.main.banner.GetAudioContentBannerRespons import kr.co.vividnext.sodalive.content.series.GetSeriesListResponse import kr.co.vividnext.sodalive.event.GetEventResponse import kr.co.vividnext.sodalive.explorer.GetExplorerSectionResponse -import kr.co.vividnext.sodalive.notice.NoticeTitleItem +import kr.co.vividnext.sodalive.notice.NoticeItem data class GetContentMainTabHomeResponse( val tabId: Long = 1, - val latestNotice: NoticeTitleItem?, + val latestNotice: NoticeItem?, val bannerList: List, val rankCreatorList: GetExplorerSectionResponse, val rankSeriesList: List, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/notice/GetNoticeResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/notice/GetNoticeResponse.kt index 246846e..89003d6 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/notice/GetNoticeResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/notice/GetNoticeResponse.kt @@ -7,14 +7,9 @@ data class GetNoticeResponse( val noticeList: List ) -data class NoticeItem( +data class NoticeItem @QueryProjection constructor( val id: Long, val title: String, val content: String, val date: String ) - -data class NoticeTitleItem @QueryProjection constructor( - val id: Long, - val title: String -) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceNoticeService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceNoticeService.kt index f76e57f..8aa890e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceNoticeService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceNoticeService.kt @@ -5,8 +5,6 @@ import org.springframework.data.domain.Pageable import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional -import java.time.ZoneId -import java.time.format.DateTimeFormatter @Service @Transactional(readOnly = true) @@ -46,25 +44,11 @@ class ServiceNoticeService(private val repository: ServiceServiceNoticeRepositor fun getNoticeList(pageable: Pageable, timezone: String): GetNoticeResponse { val totalCount = repository.getNoticeTotalCount() val noticeList = repository.getNoticeList(pageable) - .asSequence() - .map { - val createdAt = it.createdAt!! - .atZone(ZoneId.of("UTC")) - .withZoneSameInstant(ZoneId.of(timezone)) - - NoticeItem( - it.id!!, - it.title, - it.content, - createdAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) - ) - } - .toList() return GetNoticeResponse(totalCount, noticeList) } - fun getLatestNotice(): NoticeTitleItem? { + fun getLatestNotice(): NoticeItem? { return repository.getLatestNotice() } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceServiceNoticeRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceServiceNoticeRepository.kt index d5772f5..f1261e4 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceServiceNoticeRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceServiceNoticeRepository.kt @@ -1,18 +1,22 @@ package kr.co.vividnext.sodalive.notice +import com.querydsl.core.types.dsl.DateTimePath +import com.querydsl.core.types.dsl.Expressions +import com.querydsl.core.types.dsl.StringTemplate import com.querydsl.jpa.impl.JPAQueryFactory import kr.co.vividnext.sodalive.notice.QServiceNotice.serviceNotice import org.springframework.data.domain.Pageable import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository +import java.time.LocalDateTime @Repository interface ServiceServiceNoticeRepository : JpaRepository, ServiceNoticeQueryRepository interface ServiceNoticeQueryRepository { fun getNoticeTotalCount(): Int - fun getNoticeList(pageable: Pageable): List - fun getLatestNotice(): NoticeTitleItem? + fun getNoticeList(pageable: Pageable): List + fun getLatestNotice(): NoticeItem? } @Repository @@ -26,9 +30,17 @@ class ServiceNoticeQueryRepositoryImpl(private val queryFactory: JPAQueryFactory .size } - override fun getNoticeList(pageable: Pageable): List { + override fun getNoticeList(pageable: Pageable): List { return queryFactory - .selectFrom(serviceNotice) + .select( + QNoticeItem( + serviceNotice.id, + serviceNotice.title, + serviceNotice.content, + getFormattedDate(serviceNotice.createdAt) + ) + ) + .from(serviceNotice) .where(serviceNotice.isActive.isTrue) .offset(pageable.offset) .limit(pageable.pageSize.toLong()) @@ -36,12 +48,14 @@ class ServiceNoticeQueryRepositoryImpl(private val queryFactory: JPAQueryFactory .fetch() } - override fun getLatestNotice(): NoticeTitleItem? { + override fun getLatestNotice(): NoticeItem? { return queryFactory .select( - QNoticeTitleItem( + QNoticeItem( serviceNotice.id, - serviceNotice.title + serviceNotice.title, + serviceNotice.content, + getFormattedDate(serviceNotice.createdAt) ) ) .from(serviceNotice) @@ -49,4 +63,18 @@ class ServiceNoticeQueryRepositoryImpl(private val queryFactory: JPAQueryFactory .orderBy(serviceNotice.id.desc()) .fetchFirst() } + + private fun getFormattedDate(dateTimePath: DateTimePath): StringTemplate { + return Expressions.stringTemplate( + "DATE_FORMAT({0}, {1})", + Expressions.dateTimeTemplate( + LocalDateTime::class.java, + "CONVERT_TZ({0},{1},{2})", + dateTimePath, + "UTC", + "Asia/Seoul" + ), + "%Y-%m-%d" + ) + } } From b7610641e544493e38bc42c7ecc8b801d2642417 Mon Sep 17 00:00:00 2001 From: Klaus Date: Sun, 9 Feb 2025 22:58:09 +0900 Subject: [PATCH 02/26] =?UTF-8?q?=EC=B1=84=EB=84=90=EB=B3=84=20=EC=9D=B8?= =?UTF-8?q?=EA=B8=B0=20=EC=BD=98=ED=85=90=EC=B8=A0=20-=20audioTheme=20join?= =?UTF-8?q?=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=95=98=EC=97=AC=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt index 2250eee..b9fbc70 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt @@ -347,6 +347,7 @@ class RankingRepository( .and(audioContent.isActive.isTrue) .and(audioContent.duration.isNotNull) .and(audioContent.limited.isNull) + .and(audioContentTheme.isActive.isTrue) .and(order.isActive.isTrue) .and(member.id.eq(creatorId)) @@ -369,6 +370,7 @@ class RankingRepository( ) .from(order) .innerJoin(order.audioContent, audioContent) + .innerJoin(audioContent.theme, audioContentTheme) .innerJoin(audioContent.member, member) .where(where) .groupBy(audioContent.id) @@ -384,6 +386,7 @@ class RankingRepository( .and(audioContent.isActive.isTrue) .and(audioContent.duration.isNotNull) .and(audioContent.limited.isNull) + .and(audioContentTheme.isActive.isTrue) .and(order.isActive.isTrue) .and(member.id.eq(creatorId)) @@ -406,6 +409,7 @@ class RankingRepository( ) .from(order) .innerJoin(order.audioContent, audioContent) + .innerJoin(audioContent.theme, audioContentTheme) .innerJoin(audioContent.member, member) .where(where) .groupBy(audioContent.id) From c4602369aefe7b9ae56c28f9f25e2660df6d858d Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 10 Feb 2025 02:30:30 +0900 Subject: [PATCH 03/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=9E=AD?= =?UTF-8?q?=ED=82=B9=20=EC=95=84=EC=9D=B4=ED=85=9C=20-=20=ED=81=AC?= =?UTF-8?q?=EB=A6=AC=EC=97=90=EC=9D=B4=ED=84=B0=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vividnext/sodalive/content/AudioContentRepository.kt | 3 ++- .../sodalive/content/main/GetAudioContentRanking.kt | 3 ++- .../kr/co/vividnext/sodalive/rank/RankingRepository.kt | 9 ++++++--- 3 files changed, 10 insertions(+), 5 deletions(-) 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 f855b57..c8ab4c9 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt @@ -679,7 +679,8 @@ class AudioContentQueryRepositoryImpl( audioContent.price, audioContent.duration, member.id, - member.nickname + member.nickname, + member.profileImage.prepend("/").prepend(imageHost) ) ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/GetAudioContentRanking.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/GetAudioContentRanking.kt index df6ab26..e96ad30 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/GetAudioContentRanking.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/GetAudioContentRanking.kt @@ -17,5 +17,6 @@ data class GetAudioContentRankingItem @QueryProjection constructor( @JsonProperty("price") val price: Int, @JsonProperty("duration") val duration: String, @JsonProperty("creatorId") val creatorId: Long, - @JsonProperty("creatorNickname") val creatorNickname: String + @JsonProperty("creatorNickname") val creatorNickname: String, + @JsonProperty("creatorProfileImageUrl") val creatorProfileImageUrl: String ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt index b9fbc70..e44f6ce 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt @@ -82,7 +82,8 @@ class RankingRepository( audioContent.price, audioContent.duration, member.id, - member.nickname + member.nickname, + member.profileImage.prepend("/").prepend(imageHost) ) ) @@ -365,7 +366,8 @@ class RankingRepository( audioContent.price, audioContent.duration, member.id, - member.nickname + member.nickname, + member.profileImage.prepend("/").prepend(imageHost) ) ) .from(order) @@ -404,7 +406,8 @@ class RankingRepository( audioContent.price, audioContent.duration, member.id, - member.nickname + member.nickname, + member.profileImage.prepend("/").prepend(imageHost) ) ) .from(order) From dce1abaeff9839c7d2a818d37431c056cf51e87c Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 10 Feb 2025 02:39:56 +0900 Subject: [PATCH 04/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=ED=99=88=20-=20=EC=B1=84=EB=84=90=EB=B3=84=20?= =?UTF-8?q?=EC=9D=B8=EA=B8=B0=20=EC=BD=98=ED=85=90=EC=B8=A0=20API=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tab/GetPopularContentByCreatorResponse.kt | 8 ++++++++ .../home/AudioContentMainTabHomeController.kt | 16 ++++++++++++++++ .../tab/home/AudioContentMainTabHomeService.kt | 18 ++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetPopularContentByCreatorResponse.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetPopularContentByCreatorResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetPopularContentByCreatorResponse.kt new file mode 100644 index 0000000..6f8cdc8 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetPopularContentByCreatorResponse.kt @@ -0,0 +1,8 @@ +package kr.co.vividnext.sodalive.content.main.tab + +import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem + +data class GetPopularContentByCreatorResponse( + val salesRankContentList: List, + val salesCountRankContentList: List +) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeController.kt index 601f82d..20d0bea 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeController.kt @@ -6,6 +6,7 @@ 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.RequestParam import org.springframework.web.bind.annotation.RestController @RestController @@ -19,4 +20,19 @@ class AudioContentMainTabHomeController(private val service: AudioContentMainTab ApiResponse.ok(service.fetchData(member)) } + + @GetMapping("/popular-content-by-creator") + fun getPopularContentByCreator( + @RequestParam creatorId: Long, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.getPopularContentByCreator( + creatorId = creatorId, + isAdult = member.auth != null + ) + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt index 8532a33..1a1a0ec 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/home/AudioContentMainTabHomeService.kt @@ -1,6 +1,7 @@ package kr.co.vividnext.sodalive.content.main.tab.home import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerService +import kr.co.vividnext.sodalive.content.main.tab.GetPopularContentByCreatorResponse import kr.co.vividnext.sodalive.event.EventService import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.notice.ServiceNoticeService @@ -114,4 +115,21 @@ class AudioContentMainTabHomeService( salesCountRankContentList = salesCountRankContentList ) } + + fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): GetPopularContentByCreatorResponse { + val salesRankContentList = rankingService.fetchCreatorContentBySalesTop2( + creatorId = creatorId, + isAdult = isAdult + ) + + val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop2( + creatorId = creatorId, + isAdult = isAdult + ) + + return GetPopularContentByCreatorResponse( + salesRankContentList = salesRankContentList, + salesCountRankContentList = salesCountRankContentList + ) + } } From 7e9cb556d034235dd2bd6fd866d9aa734901d284 Mon Sep 17 00:00:00 2001 From: Klaus Date: Wed, 12 Feb 2025 19:27:52 +0900 Subject: [PATCH 05/26] =?UTF-8?q?=EC=8B=9C=EB=A6=AC=EC=A6=88=20=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20-=20=EC=BD=98=ED=85=90=EC=B8=A0=EA=B0=80?= =?UTF-8?q?=201=EA=B0=9C=20=EC=9D=B4=EC=83=81=20=EB=93=B1=EB=A1=9D?= =?UTF-8?q?=EB=90=9C=20=EC=8B=9C=EB=A6=AC=EC=A6=88=EB=A7=8C=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vividnext/sodalive/content/series/ContentSeriesService.kt | 3 +++ 1 file changed, 3 insertions(+) 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 1e95021..5b526ac 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 @@ -219,6 +219,9 @@ class ContentSeriesService( it } + .filter { + it.numberOfContent > 0 + } .map { val nowDateTime = LocalDateTime.now() From 63f952d390f9656ff660f59e56b42d614c008e77 Mon Sep 17 00:00:00 2001 From: Klaus Date: Wed, 12 Feb 2025 19:54:11 +0900 Subject: [PATCH 06/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20=ED=83=AD=20-=20?= =?UTF-8?q?=EC=B0=A8=EB=8B=A8=20=EB=8B=B9=ED=95=9C=20=EC=9C=A0=EC=A0=80?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A6=AC=EC=A7=80=EB=84=90=20=EC=98=A4?= =?UTF-8?q?=EB=94=94=EC=98=A4=20=EB=93=9C=EB=9D=BC=EB=A7=88=EA=B0=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tab/series/AudioContentMainTabSeriesService.kt | 14 ++++++++------ .../content/series/ContentSeriesRepository.kt | 11 +++++++++-- .../content/series/ContentSeriesService.kt | 3 ++- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt index 681dd5f..baca442 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt @@ -23,15 +23,17 @@ class AudioContentMainTabSeriesService( ) { fun fetchData(member: Member): GetContentMainTabSeriesResponse { val isAdult = member.auth != null + val memberId = member.id!! // 메인 배너 (시리즈) val contentBannerList = bannerService.getBannerList( tabId = 2, - memberId = member.id!!, + memberId = memberId, isAdult = isAdult ) val originalAudioDrama = seriesService.getOriginalAudioDramaList( + memberId = memberId, isAdult = isAdult, offset = 0, limit = 20 @@ -48,7 +50,7 @@ class AudioContentMainTabSeriesService( .plusDays(1) val rankSeriesList = rankingService.getSeriesRanking( - memberId = member.id!!, + memberId = memberId, isAdult = isAdult, startDate = dailyRankingStartDate, endDate = dailyRankingEndDate @@ -60,7 +62,7 @@ class AudioContentMainTabSeriesService( // 장르별 추천 시리즈 val recommendSeriesList = if (genreList.isNotEmpty()) { rankingService.getSeriesAllRankingByGenre( - memberId = member.id!!, + memberId = memberId, isAdult = isAdult, genreId = genreList[0].id ) @@ -82,7 +84,7 @@ class AudioContentMainTabSeriesService( .plusMonths(1) val rankCompleteSeriesList = rankingService.getCompleteSeriesRanking( - memberId = member.id!!, + memberId = memberId, isAdult = isAdult, startDate = monthlyRankingStartDate, endDate = monthlyRankingEndDate @@ -98,7 +100,7 @@ class AudioContentMainTabSeriesService( .plusDays(6) val seriesRankCreatorList = rankingService.fetchCreatorBySeriesRevenueRankTop20( - memberId = member.id!!, + memberId = memberId, startDate = startDate.minusDays(1), endDate = endDate ) @@ -122,7 +124,7 @@ class AudioContentMainTabSeriesService( title = it.title, items = seriesService.fetchSeriesByCurationId( curationId = it.id!!, - memberId = member.id!!, + memberId = memberId, isAdult = isAdult ) ) 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 e87f059..e91df51 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 @@ -35,7 +35,7 @@ interface ContentSeriesQueryRepository { fun getKeywordList(seriesId: Long): List fun getSeriesContentMinMaxPrice(seriesId: Long): GetSeriesContentMinMaxPriceResponse fun getRecommendSeriesList(isAuth: Boolean, contentType: ContentType, limit: Long): List - fun getOriginalAudioDramaList(isAdult: Boolean, offset: Long = 0, limit: Long = 20): List + fun getOriginalAudioDramaList(memberId: Long, isAdult: Boolean, offset: Long = 0, limit: Long = 20): List fun getGenreList(isAdult: Boolean): List fun findByCurationId(curationId: Long, memberId: Long, isAdult: Boolean): List } @@ -143,9 +143,14 @@ class ContentSeriesQueryRepositoryImpl( .fetch() } - override fun getOriginalAudioDramaList(isAdult: Boolean, offset: Long, limit: Long): List { + override fun getOriginalAudioDramaList(memberId: Long, isAdult: Boolean, offset: Long, limit: Long): List { + val blockMemberCondition = blockMember.member.id.eq(member.id) + .and(blockMember.isActive.isTrue) + .and(blockMember.blockedMember.id.eq(memberId)) + var where = series.isOriginal.isTrue .and(series.isActive.isTrue) + .and(blockMember.id.isNull) if (!isAdult) { where = where.and(series.isAdult.isFalse) @@ -153,6 +158,8 @@ class ContentSeriesQueryRepositoryImpl( return queryFactory .selectFrom(series) + .innerJoin(series.member, member) + .leftJoin(blockMember).on(blockMemberCondition) .where(where) .orderBy(Expressions.numberTemplate(Double::class.java, "function('rand')").asc()) .offset(offset) 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 5b526ac..e3a7db1 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 @@ -31,11 +31,12 @@ class ContentSeriesService( private val coverImageHost: String ) { fun getOriginalAudioDramaList( + memberId: Long, isAdult: Boolean, offset: Long = 0, limit: Long = 20 ): List { - val originalAudioDramaList = repository.getOriginalAudioDramaList(isAdult, offset, limit) + val originalAudioDramaList = repository.getOriginalAudioDramaList(memberId, isAdult, offset, limit) return seriesToSeriesListItem(originalAudioDramaList, isAdult) } From a6e949bdd6d7f899168f04a1273ca609454d6a45 Mon Sep 17 00:00:00 2001 From: Klaus Date: Wed, 12 Feb 2025 23:48:41 +0900 Subject: [PATCH 07/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20=ED=83=AD=20-=20?= =?UTF-8?q?=EC=9E=A5=EB=A5=B4=EB=B3=84=20=EC=B6=94=EC=B2=9C=20=EC=8B=9C?= =?UTF-8?q?=EB=A6=AC=EC=A6=88=20=EC=A0=95=EB=A0=AC=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?-=20=ED=8C=90=EB=A7=A4=20=EC=BA=94=20->=20=ED=8C=90=EB=A7=A4=20?= =?UTF-8?q?=EA=B0=9C=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt index e44f6ce..6f639cc 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt @@ -289,7 +289,7 @@ class RankingRepository( .where(where) .groupBy(series.id) .orderBy( - order.can.sum().desc(), + order.id.countDistinct().desc(), Expressions.numberTemplate(Double::class.java, "function('rand')").asc() ) .offset(0) From 39eb3d48a866bd6b74d8233d59b79ec1cf3b4333 Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 13 Feb 2025 01:20:18 +0900 Subject: [PATCH 08/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20=ED=83=AD=20-=20?= =?UTF-8?q?=EC=83=88=EB=A1=9C=EC=9A=B4=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20-?= =?UTF-8?q?=20=ED=81=AC=EB=A6=AC=EC=97=90=EC=9D=B4=ED=84=B0=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/main/tab/GetRecommendSeriesListResponse.kt | 3 ++- .../sodalive/content/main/tab/RecommendSeriesRepository.kt | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetRecommendSeriesListResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetRecommendSeriesListResponse.kt index a84a20d..eca4655 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetRecommendSeriesListResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/GetRecommendSeriesListResponse.kt @@ -7,5 +7,6 @@ data class GetRecommendSeriesListResponse @QueryProjection constructor( val title: String, val imageUrl: String, val creatorId: Long, - val creatorNickname: String + val creatorNickname: String, + val creatorProfileImageUrl: String ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/RecommendSeriesRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/RecommendSeriesRepository.kt index b17a583..97e5975 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/RecommendSeriesRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/RecommendSeriesRepository.kt @@ -30,7 +30,8 @@ class RecommendSeriesRepository( series.title, recommendSeries.imagePath.prepend("/").prepend(imageHost), member.id, - member.nickname + member.nickname, + member.profileImage.prepend("/").prepend(imageHost) ) ) .from(recommendSeries) @@ -57,7 +58,8 @@ class RecommendSeriesRepository( series.title, recommendSeries.imagePath.prepend("/").prepend(imageHost), member.id, - member.nickname + member.nickname, + member.profileImage.prepend("/").prepend(imageHost) ) ) .from(recommendSeries) From ca9e7da17eb62f63074fac4cf9c912303068785e Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 13 Feb 2025 02:08:09 +0900 Subject: [PATCH 09/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20=ED=83=AD=20-=20?= =?UTF-8?q?=EC=B1=84=EB=84=90=EB=B3=84=20=EC=B6=94=EC=B2=9C=20=EC=8B=9C?= =?UTF-8?q?=EB=A6=AC=EC=A6=88=20=EB=B3=80=EC=88=98=EB=AA=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20-=20salesRankContentList=20->=20recommendSeriesByCh?= =?UTF-8?q?annel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/main/tab/series/AudioContentMainTabSeriesService.kt | 2 +- .../content/main/tab/series/GetContentMainTabSeriesResponse.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt index baca442..33efe70 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt @@ -143,7 +143,7 @@ class AudioContentMainTabSeriesService( newSeriesList = newSeriesList, rankCompleteSeriesList = rankCompleteSeriesList, seriesRankCreatorList = seriesRankCreatorList, - salesRankContentList = salesRankContentList, + recommendSeriesByChannel = salesRankContentList, eventBannerList = eventBannerList, curationList = curationList ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/GetContentMainTabSeriesResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/GetContentMainTabSeriesResponse.kt index d7155b0..36a3b15 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/GetContentMainTabSeriesResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/GetContentMainTabSeriesResponse.kt @@ -17,7 +17,7 @@ data class GetContentMainTabSeriesResponse( val newSeriesList: List, val rankCompleteSeriesList: List, val seriesRankCreatorList: List, - val salesRankContentList: List, + val recommendSeriesByChannel: List, val eventBannerList: GetEventResponse, val curationList: List ) From 664677a005b38e098b7c4c0cc67a921b8dbfe0c4 Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 13 Feb 2025 14:01:09 +0900 Subject: [PATCH 10/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=8B=A8=ED=8E=B8=20=ED=83=AD=20-=20=EC=83=88?= =?UTF-8?q?=EB=A1=9C=EC=9A=B4=20=EB=8B=A8=ED=8E=B8=20=EC=B2=AB=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=EC=8B=9C=20=ED=85=8C=EB=A7=88=20=EC=97=86=EC=9D=B4=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AudioContentMainTabContentService.kt | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) 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 index 6807e14..f505e2e 100644 --- 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 @@ -33,18 +33,14 @@ class AudioContentMainTabContentService( 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 newContentList = audioContentRepository.findByTheme( + memberId = member.id!!, + theme = "", + isAdult = member.auth != null, + contentType = ContentType.ALL, + offset = 0, + limit = 10 + ) // 일간 랭킹 val currentDateTime = LocalDateTime.now() From ecddf9975f107c478e0d17712e7cf0a47f174f37 Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 13 Feb 2025 14:15:34 +0900 Subject: [PATCH 11/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=8B=A8=ED=8E=B8=20=ED=83=AD=20-=20=ED=85=8C?= =?UTF-8?q?=EB=A7=88=EB=B3=84=20=EC=BD=98=ED=85=90=EC=B8=A0=20API=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AudioContentMainTabContentController.kt | 33 ++++++++++++++++++- .../AudioContentMainTabContentService.kt | 23 ++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) 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 index 80762a1..375d316 100644 --- 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 @@ -2,10 +2,13 @@ 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.content.ContentType import kr.co.vividnext.sodalive.member.Member +import org.springframework.data.domain.Pageable 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.RequestParam import org.springframework.web.bind.annotation.RestController @RestController @@ -13,10 +16,38 @@ import org.springframework.web.bind.annotation.RestController class AudioContentMainTabContentController(private val service: AudioContentMainTabContentService) { @GetMapping fun fetchContentMainTabContent( + @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("/new-content-by-theme") + fun getNewContentByTheme( + @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 { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.getNewContentByTheme( + theme, + isAdultContentVisible = isAdultContentVisible ?: true, + contentType = contentType ?: ContentType.ALL, + 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 index f505e2e..8c20e44 100644 --- 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 @@ -2,6 +2,7 @@ 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.GetAudioContentMainItem import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerService import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository import kr.co.vividnext.sodalive.event.EventService @@ -18,7 +19,11 @@ class AudioContentMainTabContentService( private val rankingService: RankingService, private val eventService: EventService ) { - fun fetchData(member: Member): GetContentMainTabContentResponse { + fun fetchData( + isAdultContentVisible: Boolean, + contentType: ContentType, + member: Member + ): GetContentMainTabContentResponse { val memberId = member.id!! val isAdult = member.auth != null @@ -98,4 +103,20 @@ class AudioContentMainTabContentService( eventBannerList = eventBannerList ) } + + fun getNewContentByTheme( + theme: String, + isAdultContentVisible: Boolean, + contentType: ContentType, + member: Member + ): List { + return audioContentRepository.findByTheme( + memberId = member.id!!, + theme = theme, + isAdult = member.auth != null && isAdultContentVisible, + contentType = contentType, + offset = 0, + limit = 10 + ) + } } From 2f0182e06c54cdab37f647c51ffbe5746bcefdfb Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 13 Feb 2025 14:37:44 +0900 Subject: [PATCH 12/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=8B=A8=ED=8E=B8=20=ED=83=AD=20-=20=EC=BD=98?= =?UTF-8?q?=ED=85=90=EC=B8=A0=20=EC=9D=BC=EA=B0=84=20=EB=9E=AD=ED=82=B9=20?= =?UTF-8?q?API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AudioContentMainTabContentController.kt | 17 ++++++++++++++ .../AudioContentMainTabContentService.kt | 23 +++++++++++++++++++ 2 files changed, 40 insertions(+) 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 index 375d316..8a7fe18 100644 --- 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 @@ -31,6 +31,23 @@ class AudioContentMainTabContentController(private val service: AudioContentMain ) } + @GetMapping("/ranking") + fun getAudioContentRanking( + @RequestParam("sort-type", required = false) sortType: String? = "매출", + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?, + pageable: Pageable + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.getAudioContentRanking( + memberId = member.id!!, + isAdult = member.auth != null, + sortType = sortType ?: "매출" + ) + ) + } + @GetMapping("/new-content-by-theme") fun getNewContentByTheme( @RequestParam("theme") theme: String, 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 index 8c20e44..eb7b011 100644 --- 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 @@ -3,6 +3,7 @@ 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.GetAudioContentMainItem +import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerService import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository import kr.co.vividnext.sodalive.event.EventService @@ -104,6 +105,28 @@ class AudioContentMainTabContentService( ) } + fun getAudioContentRanking( + memberId: Long, + isAdult: Boolean, + sortType: String = "매출" + ): List { + val currentDateTime = LocalDateTime.now() + val dailyRankingStartDate = currentDateTime + .withHour(15) + .withMinute(0) + .withSecond(0) + .minusDays(2) + val dailyRankingEndDate = dailyRankingStartDate + .plusDays(1) + + return rankingService.getContentRanking( + memberId = memberId, + isAdult = isAdult, + startDate = dailyRankingStartDate, + endDate = dailyRankingEndDate + ) + } + fun getNewContentByTheme( theme: String, isAdultContentVisible: Boolean, From 258bd0796d6bf1f48c24d56b264b875c3adea84e Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 13 Feb 2025 14:56:51 +0900 Subject: [PATCH 13/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=8B=A8=ED=8E=B8=20=ED=83=AD=20-=20=EC=B1=84?= =?UTF-8?q?=EB=84=90=EB=B3=84=20=EC=B6=94=EC=B2=9C=20=EB=8B=A8=ED=8E=B8=20?= =?UTF-8?q?API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AudioContentMainTabContentController.kt | 15 +++++++++++++++ .../AudioContentMainTabContentService.kt | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) 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 index 8a7fe18..f50efb8 100644 --- 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 @@ -67,4 +67,19 @@ class AudioContentMainTabContentController(private val service: AudioContentMain ) ) } + + @GetMapping("/popular-content-by-creator") + fun getPopularContentByCreator( + @RequestParam creatorId: Long, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.getPopularContentByCreator( + creatorId = creatorId, + isAdult = member.auth != null + ) + ) + } } 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 index eb7b011..205951e 100644 --- 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 @@ -5,6 +5,7 @@ import kr.co.vividnext.sodalive.content.ContentType import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem import kr.co.vividnext.sodalive.content.main.GetAudioContentRankingItem import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerService +import kr.co.vividnext.sodalive.content.main.tab.GetPopularContentByCreatorResponse import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository import kr.co.vividnext.sodalive.event.EventService import kr.co.vividnext.sodalive.member.Member @@ -142,4 +143,21 @@ class AudioContentMainTabContentService( limit = 10 ) } + + fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): GetPopularContentByCreatorResponse { + val salesRankContentList = rankingService.fetchCreatorContentBySalesTop2( + creatorId = creatorId, + isAdult = isAdult + ) + + val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop2( + creatorId = creatorId, + isAdult = isAdult + ) + + return GetPopularContentByCreatorResponse( + salesRankContentList = salesRankContentList, + salesCountRankContentList = salesCountRankContentList + ) + } } From babfb27b1f2bfb36e967704d839c1ac5b8e46b9d Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 14 Feb 2025 01:32:57 +0900 Subject: [PATCH 14/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=AC=B4=EB=A3=8C=20=ED=83=AD=20-=20=ED=81=90?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98=EC=97=90=EC=84=9C=20'=ED=81=AC?= =?UTF-8?q?=EB=A6=AC=EC=97=90=EC=9D=B4=ED=84=B0=20=EC=86=8C=EA=B0=9C'=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/main/tab/free/AudioContentMainTabFreeService.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt index b64a2ab..920178e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt @@ -64,6 +64,7 @@ class AudioContentMainTabFreeService( } val curationList = curationRepository.findByContentMainTabId(tabId = tabId, isAdult = isAdult) + .filter { it.title != "크리에이터 소개" } .map { GetContentCurationResponse( title = it.title, From bebfda03435aef2053eda2d38a7ad6c252fc76eb Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 14 Feb 2025 03:20:18 +0900 Subject: [PATCH 15/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20=ED=83=AD=20-=20?= =?UTF-8?q?=EC=98=A4=EB=A6=AC=EC=A7=80=EB=84=90=20=EB=93=9C=EB=9D=BC?= =?UTF-8?q?=EB=A7=88=20=EC=A0=84=EC=B2=B4=EB=B3=B4=EA=B8=B0=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AudioContentMainTabSeriesController.kt | 18 ++++++++++++++ .../AudioContentMainTabSeriesService.kt | 18 ++++++++++++++ .../content/series/ContentSeriesRepository.kt | 24 +++++++++++++++++++ .../content/series/ContentSeriesService.kt | 4 ++++ 4 files changed, 64 insertions(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt index 1e27aa6..f9ff1af 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt @@ -3,6 +3,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.member.Member +import org.springframework.data.domain.Pageable import org.springframework.security.core.annotation.AuthenticationPrincipal import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping @@ -19,4 +20,21 @@ class AudioContentMainTabSeriesController(private val service: AudioContentMainT ApiResponse.ok(service.fetchData(member)) } + + @GetMapping("/original") + fun getOriginalAudioDramaList( + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?, + pageable: Pageable + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.getOriginalAudioDramaList( + memberId = member.id!!, + isAdult = member.auth != null, + offset = pageable.offset, + limit = pageable.pageSize.toLong() + ) + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt index 33efe70..2bcdc14 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt @@ -4,6 +4,7 @@ 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 import kr.co.vividnext.sodalive.content.series.ContentSeriesService +import kr.co.vividnext.sodalive.content.series.GetSeriesListResponse import kr.co.vividnext.sodalive.event.EventService import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.rank.RankingService @@ -148,4 +149,21 @@ class AudioContentMainTabSeriesService( curationList = curationList ) } + + fun getOriginalAudioDramaList( + memberId: Long, + isAdult: Boolean, + offset: Long, + limit: Long + ): GetSeriesListResponse { + val totalCount = seriesService.getOriginalAudioDramaTotalCount(memberId, isAdult) + val items = seriesService.getOriginalAudioDramaList( + memberId = memberId, + isAdult = isAdult, + offset = 0, + limit = 20 + ) + + return GetSeriesListResponse(totalCount, items) + } } 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 e91df51..c769fbf 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 @@ -36,6 +36,7 @@ interface ContentSeriesQueryRepository { fun getSeriesContentMinMaxPrice(seriesId: Long): GetSeriesContentMinMaxPriceResponse fun getRecommendSeriesList(isAuth: Boolean, contentType: ContentType, limit: Long): List fun getOriginalAudioDramaList(memberId: Long, isAdult: Boolean, offset: Long = 0, limit: Long = 20): List + fun getOriginalAudioDramaTotalCount(memberId: Long, isAdult: Boolean): Int fun getGenreList(isAdult: Boolean): List fun findByCurationId(curationId: Long, memberId: Long, isAdult: Boolean): List } @@ -167,6 +168,29 @@ class ContentSeriesQueryRepositoryImpl( .fetch() } + override fun getOriginalAudioDramaTotalCount(memberId: Long, isAdult: Boolean): Int { + val blockMemberCondition = blockMember.member.id.eq(member.id) + .and(blockMember.isActive.isTrue) + .and(blockMember.blockedMember.id.eq(memberId)) + + var where = series.isOriginal.isTrue + .and(series.isActive.isTrue) + .and(blockMember.id.isNull) + + if (!isAdult) { + where = where.and(series.isAdult.isFalse) + } + + return queryFactory + .select(series.id) + .from(series) + .innerJoin(series.member, member) + .leftJoin(blockMember).on(blockMemberCondition) + .where(where) + .fetch() + .size + } + override fun getGenreList(isAdult: Boolean): List { var where = seriesGenre.isActive.isTrue 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 e3a7db1..cac46b9 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 @@ -30,6 +30,10 @@ 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 getOriginalAudioDramaList( memberId: Long, isAdult: Boolean, From 10dd50b33253236d1f2654f2d4a3baf460f6e068 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 14 Feb 2025 03:30:50 +0900 Subject: [PATCH 16/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20=ED=83=AD=20-=20?= =?UTF-8?q?=EC=98=A4=EB=A6=AC=EC=A7=80=EB=84=90=20=EB=93=9C=EB=9D=BC?= =?UTF-8?q?=EB=A7=88=20=EC=A0=84=EC=B2=B4=EB=B3=B4=EA=B8=B0=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/tab/series/AudioContentMainTabSeriesService.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt index 2bcdc14..45e05a2 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt @@ -160,8 +160,8 @@ class AudioContentMainTabSeriesService( val items = seriesService.getOriginalAudioDramaList( memberId = memberId, isAdult = isAdult, - offset = 0, - limit = 20 + offset = offset, + limit = limit ) return GetSeriesListResponse(totalCount, items) From a8589ef4e733e570d2e75f2d5ad632758688a252 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 14 Feb 2025 04:31:05 +0900 Subject: [PATCH 17/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20=ED=83=AD=20-=20?= =?UTF-8?q?=EC=99=84=EA=B2=B0=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=EB=B3=B4=EA=B8=B0=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AudioContentMainTabSeriesController.kt | 17 +++++++ .../AudioContentMainTabSeriesService.kt | 34 ++++++++++++++ .../sodalive/rank/RankingRepository.kt | 47 +++++++++++++++++-- .../vividnext/sodalive/rank/RankingService.kt | 14 ++++++ 4 files changed, 108 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt index f9ff1af..3b753f5 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt @@ -37,4 +37,21 @@ class AudioContentMainTabSeriesController(private val service: AudioContentMainT ) ) } + + @GetMapping("/completed-monthly-rank") + fun getRankMonthlyCompletedSeriesList( + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?, + pageable: Pageable + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.getRankMonthlyCompletedSeriesList( + memberId = member.id!!, + isAdult = member.auth != null, + offset = pageable.offset, + limit = pageable.pageSize.toLong() + ) + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt index 45e05a2..bd7093b 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt @@ -166,4 +166,38 @@ class AudioContentMainTabSeriesService( return GetSeriesListResponse(totalCount, items) } + + fun getRankMonthlyCompletedSeriesList( + memberId: Long, + isAdult: Boolean, + offset: Long, + limit: Long + ): GetSeriesListResponse { + val monthlyRankingStartDate = LocalDateTime.now() + .withDayOfMonth(1) + .withHour(15) + .withMinute(0) + .withSecond(0) + .minusDays(1) + val monthlyRankingEndDate = monthlyRankingStartDate + .plusMonths(1) + + val totalCount = rankingService.getCompleteSeriesRankingTotalCount( + memberId = memberId, + isAdult = isAdult, + startDate = monthlyRankingStartDate, + endDate = monthlyRankingEndDate + ) + + val items = rankingService.getCompleteSeriesRanking( + memberId = memberId, + isAdult = isAdult, + startDate = monthlyRankingStartDate, + endDate = monthlyRankingEndDate, + offset = offset, + limit = limit + ) + + return GetSeriesListResponse(totalCount, items) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt index 6f639cc..cf804a5 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt @@ -209,6 +209,48 @@ class RankingRepository( .fetch() } + fun getCompleteSeriesRankingTotalCount( + memberId: Long, + isAdult: Boolean, + startDate: LocalDateTime, + endDate: LocalDateTime + ): Int { + val blockMemberCondition = blockMember.member.id.eq(member.id) + .and(blockMember.isActive.isTrue) + .and(blockMember.blockedMember.id.eq(memberId)) + + var where = series.isActive.isTrue + .and(series.state.eq(SeriesState.COMPLETE)) + .and(audioContent.isActive.isTrue) + .and(member.isActive.isTrue) + .and(member.isNotNull) + .and(member.role.eq(MemberRole.CREATOR)) + .and(audioContent.duration.isNotNull) + .and(audioContent.limited.isNull) + .and(blockMember.id.isNull) + .and(order.isActive.isTrue) + .and(order.createdAt.goe(startDate)) + .and(order.createdAt.lt(endDate)) + + if (!isAdult) { + where = where.and(series.isAdult.isFalse) + } + + return queryFactory + .select(series.id) + .from(seriesContent) + .innerJoin(seriesContent.series, series) + .innerJoin(seriesContent.content, audioContent) + .innerJoin(series.member, member) + .leftJoin(order).on(audioContent.id.eq(order.audioContent.id)) + .leftJoin(blockMember).on(blockMemberCondition) + .where(where) + .groupBy(series.id) + .orderBy(order.can.sum().desc()) + .fetch() + .size + } + fun getCompleteSeriesRanking( memberId: Long, isAdult: Boolean, @@ -248,10 +290,7 @@ class RankingRepository( .leftJoin(blockMember).on(blockMemberCondition) .where(where) .groupBy(series.id) - .orderBy( - order.can.sum().desc(), - Expressions.numberTemplate(Double::class.java, "function('rand')").asc() - ) + .orderBy(order.can.sum().desc()) .offset(offset) .limit(limit) .fetch() diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt index a3504fc..f9aac15 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt @@ -82,6 +82,20 @@ class RankingService( return seriesToSeriesListItem(seriesList = seriesList, isAdult = isAdult) } + fun getCompleteSeriesRankingTotalCount( + memberId: Long, + isAdult: Boolean, + startDate: LocalDateTime, + endDate: LocalDateTime + ): Int { + return repository.getCompleteSeriesRankingTotalCount( + memberId = memberId, + isAdult = isAdult, + startDate = startDate, + endDate = endDate + ) + } + fun getCompleteSeriesRanking( memberId: Long, isAdult: Boolean, From 9c9aa336876f9ab88a690e5facb34d832c6f9f6d Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 14 Feb 2025 04:50:13 +0900 Subject: [PATCH 18/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20=ED=83=AD=20-=20?= =?UTF-8?q?=EC=9E=A5=EB=A5=B4=EB=B3=84=20=EC=B6=94=EC=B2=9C=20=EC=8B=9C?= =?UTF-8?q?=EB=A6=AC=EC=A6=88=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AudioContentMainTabSeriesController.kt | 17 +++++++++++++++++ .../series/AudioContentMainTabSeriesService.kt | 12 ++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt index 3b753f5..4a4d2e0 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt @@ -7,6 +7,7 @@ import org.springframework.data.domain.Pageable 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.RequestParam import org.springframework.web.bind.annotation.RestController @RestController @@ -54,4 +55,20 @@ class AudioContentMainTabSeriesController(private val service: AudioContentMainT ) ) } + + @GetMapping("/recommend-by-genre") + fun getRecommendSeriesListByGenre( + @RequestParam genreId: Long, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.getRecommendSeriesListByGenre( + genreId, + memberId = member.id!!, + isAdult = member.auth != null + ) + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt index bd7093b..48f2497 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt @@ -200,4 +200,16 @@ class AudioContentMainTabSeriesService( return GetSeriesListResponse(totalCount, items) } + + fun getRecommendSeriesListByGenre( + genreId: Long, + memberId: Long, + isAdult: Boolean + ): List { + return rankingService.getSeriesAllRankingByGenre( + memberId = memberId, + isAdult = isAdult, + genreId = genreId + ) + } } From 60ce64d3e1e7f44788834cd0680f994f9ac65d81 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 14 Feb 2025 04:57:41 +0900 Subject: [PATCH 19/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20=ED=83=AD=20-=20?= =?UTF-8?q?=EC=98=A4=EB=A6=AC=EC=A7=80=EB=84=90=20=EC=BD=98=ED=85=90?= =?UTF-8?q?=EC=B8=A0=20API=20-=20id=20=EB=82=B4=EB=A6=BC=EC=B0=A8=EC=88=9C?= =?UTF-8?q?=20=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/content/series/ContentSeriesRepository.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c769fbf..147d503 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 @@ -162,7 +162,7 @@ class ContentSeriesQueryRepositoryImpl( .innerJoin(series.member, member) .leftJoin(blockMember).on(blockMemberCondition) .where(where) - .orderBy(Expressions.numberTemplate(Double::class.java, "function('rand')").asc()) + .orderBy(series.id.desc()) .offset(offset) .limit(limit) .fetch() From 3caaa151f4952c8d2a585704631f8b1f09daf510 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 14 Feb 2025 14:09:21 +0900 Subject: [PATCH 20/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20=ED=83=AD=20-=20?= =?UTF-8?q?=EC=B1=84=EB=84=90=EB=B3=84=20=EC=B6=94=EC=B2=9C=20=EC=8B=9C?= =?UTF-8?q?=EB=A6=AC=EC=A6=88=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../series/AudioContentMainTabSeriesController.kt | 15 +++++++++++++++ .../series/AudioContentMainTabSeriesService.kt | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt index 4a4d2e0..e9577a0 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesController.kt @@ -71,4 +71,19 @@ class AudioContentMainTabSeriesController(private val service: AudioContentMainT ) ) } + + @GetMapping("/recommend-series-by-creator") + fun getRecommendSeriesByCreator( + @RequestParam creatorId: Long, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.getRecommendSeriesByCreator( + creatorId = creatorId, + isAdult = member.auth != null + ) + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt index 48f2497..9db205e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/series/AudioContentMainTabSeriesService.kt @@ -212,4 +212,11 @@ class AudioContentMainTabSeriesService( genreId = genreId ) } + + fun getRecommendSeriesByCreator(creatorId: Long, isAdult: Boolean): List { + return rankingService.fetchCreatorSeriesBySales( + creatorId = creatorId, + isAdult = isAdult + ) + } } From cf538a2c3645a5a42cdb715dfb8e554816bbb889 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 14 Feb 2025 14:39:22 +0900 Subject: [PATCH 21/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=ED=83=AD=20-=20=ED=81=90=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=85=98=20=EC=A1=B0=ED=9A=8C=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/AudioContentRepository.kt | 51 +++++++++++++++++++ .../alarm/AudioContentMainTabAlarmService.kt | 6 +-- .../asmr/AudioContentMainTabAsmrService.kt | 6 +-- .../free/AudioContentMainTabFreeService.kt | 12 ++--- .../AudioContentMainTabLiveReplayService.kt | 6 +-- 5 files changed, 66 insertions(+), 15 deletions(-) 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 c8ab4c9..249ec7e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt @@ -15,6 +15,7 @@ import kr.co.vividnext.sodalive.content.main.banner.AudioContentBanner import kr.co.vividnext.sodalive.content.main.banner.QAudioContentBanner.audioContentBanner import kr.co.vividnext.sodalive.content.main.curation.AudioContentCuration import kr.co.vividnext.sodalive.content.main.curation.QAudioContentCuration.audioContentCuration +import kr.co.vividnext.sodalive.content.main.curation.QAudioContentCurationItem.audioContentCurationItem import kr.co.vividnext.sodalive.content.main.tab.QAudioContentMainTab.audioContentMainTab import kr.co.vividnext.sodalive.content.order.QOrder.order import kr.co.vividnext.sodalive.content.pin.QPinContent.pinContent @@ -109,6 +110,12 @@ interface AudioContentQueryRepository { contentType: ContentType ): List + fun findAudioContentByCurationIdV2( + curationId: Long, + memberId: Long, + isAdult: Boolean + ): List + fun getAudioContentRanking( cloudfrontHost: String, isAdult: Boolean, @@ -648,6 +655,50 @@ class AudioContentQueryRepositoryImpl( .fetch() } + override fun findAudioContentByCurationIdV2( + curationId: Long, + memberId: Long, + isAdult: Boolean + ): List { + val blockMemberCondition = blockMember.member.id.eq(member.id) + .and(blockMember.isActive.isTrue) + .and(blockMember.blockedMember.id.eq(memberId)) + + var where = audioContentCuration.isActive.isTrue + .and(audioContentCurationItem.isActive.isTrue) + .and(audioContent.isActive.isTrue) + .and(audioContent.member.isNotNull) + .and(audioContent.duration.isNotNull) + .and(audioContent.member.isActive.isTrue) + .and(audioContentCuration.id.eq(curationId)) + .and(blockMember.id.isNull) + + if (!isAdult) { + where = where.and(audioContent.isAdult.isFalse) + } + + return queryFactory + .select( + QGetAudioContentMainItem( + audioContent.id, + audioContent.coverImage.prepend("/").prepend(imageHost), + audioContent.title, + member.id, + member.profileImage.prepend("/").prepend(imageHost), + member.nickname, + audioContent.price, + audioContent.duration + ) + ) + .from(audioContentCurationItem) + .innerJoin(audioContentCurationItem.content, audioContent) + .innerJoin(audioContentCurationItem.curation, audioContentCuration) + .innerJoin(audioContent.member, member) + .leftJoin(blockMember).on(blockMemberCondition) + .where(where) + .fetch() + } + override fun getAudioContentRanking( cloudfrontHost: String, isAdult: Boolean, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmService.kt index 81128fe..a2bf598 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmService.kt @@ -64,10 +64,10 @@ class AudioContentMainTabAlarmService( .map { GetContentCurationResponse( title = it.title, - items = contentRepository.findAudioContentByCurationId( + items = contentRepository.findAudioContentByCurationIdV2( curationId = it.id!!, - isAdult = isAdult, - contentType = ContentType.ALL + memberId = memberId, + isAdult = isAdult ) ) } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt index 9748778..a8bcde8 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt @@ -65,10 +65,10 @@ class AudioContentMainTabAsmrService( .map { GetContentCurationResponse( title = it.title, - items = contentRepository.findAudioContentByCurationId( + items = contentRepository.findAudioContentByCurationIdV2( curationId = it.id!!, - isAdult = isAdult, - contentType = ContentType.ALL + memberId = memberId, + isAdult = isAdult ) ) } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt index 920178e..8debfd6 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt @@ -38,10 +38,10 @@ class AudioContentMainTabFreeService( .map { GetContentCurationResponse( title = it.title, - items = contentRepository.findAudioContentByCurationId( + items = contentRepository.findAudioContentByCurationIdV2( curationId = it.id!!, - isAdult = isAdult, - contentType = ContentType.ALL + memberId = memberId, + isAdult = isAdult ) ) } @@ -68,10 +68,10 @@ class AudioContentMainTabFreeService( .map { GetContentCurationResponse( title = it.title, - items = contentRepository.findAudioContentByCurationId( + items = contentRepository.findAudioContentByCurationIdV2( curationId = it.id!!, - isAdult = isAdult, - contentType = ContentType.ALL + memberId = memberId, + isAdult = isAdult ) ) } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt index 560ca76..767a8c9 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt @@ -65,10 +65,10 @@ class AudioContentMainTabLiveReplayService( .map { GetContentCurationResponse( title = it.title, - items = contentRepository.findAudioContentByCurationId( + items = contentRepository.findAudioContentByCurationIdV2( curationId = it.id!!, - isAdult = isAdult, - contentType = ContentType.ALL + memberId = memberId, + isAdult = isAdult ) ) } From a6f8f6a4d4be682980992139cfb5689b98de06ee Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 14 Feb 2025 15:07:41 +0900 Subject: [PATCH 22/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=AC=B4=EB=A3=8C=20=ED=83=AD=20-=20=ED=81=AC?= =?UTF-8?q?=EB=A6=AC=EC=97=90=EC=9D=B4=ED=84=B0=20=EC=86=8C=EA=B0=9C=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=EB=B3=B4=EA=B8=B0=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/AudioContentRepository.kt | 10 ++++++-- .../AudioContentCurationQueryRepository.kt | 4 +--- .../free/AudioContentMainTabFreeController.kt | 17 +++++++++++++ .../free/AudioContentMainTabFreeService.kt | 24 +++++++++++++++++++ 4 files changed, 50 insertions(+), 5 deletions(-) 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 249ec7e..6451801 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt @@ -113,7 +113,9 @@ interface AudioContentQueryRepository { fun findAudioContentByCurationIdV2( curationId: Long, memberId: Long, - isAdult: Boolean + isAdult: Boolean, + offset: Long = 0, + limit: Long = 20 ): List fun getAudioContentRanking( @@ -658,7 +660,9 @@ class AudioContentQueryRepositoryImpl( override fun findAudioContentByCurationIdV2( curationId: Long, memberId: Long, - isAdult: Boolean + isAdult: Boolean, + offset: Long, + limit: Long ): List { val blockMemberCondition = blockMember.member.id.eq(member.id) .and(blockMember.isActive.isTrue) @@ -696,6 +700,8 @@ class AudioContentQueryRepositoryImpl( .innerJoin(audioContent.member, member) .leftJoin(blockMember).on(blockMemberCondition) .where(where) + .offset(offset) + .limit(limit) .fetch() } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationQueryRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationQueryRepository.kt index 28c6985..43bb72c 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationQueryRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/curation/AudioContentCurationQueryRepository.kt @@ -109,9 +109,7 @@ class AudioContentCurationQueryRepository(private val queryFactory: JPAQueryFact fun findByContentMainTabIdAndTitle( tabId: Long, title: String, - isAdult: Boolean, - offset: Long = 0, - limit: Long = 12 + isAdult: Boolean ): List { var where = audioContentCuration.isActive.isTrue .and(audioContentMainTab.id.eq(tabId)) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeController.kt index e588782..d92a08a 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeController.kt @@ -3,6 +3,7 @@ package kr.co.vividnext.sodalive.content.main.tab.free import kr.co.vividnext.sodalive.common.ApiResponse import kr.co.vividnext.sodalive.common.SodaException import kr.co.vividnext.sodalive.member.Member +import org.springframework.data.domain.Pageable import org.springframework.security.core.annotation.AuthenticationPrincipal import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping @@ -19,4 +20,20 @@ class AudioContentMainTabFreeController(private val service: AudioContentMainTab ApiResponse.ok(service.fetchData(member)) } + + @GetMapping("/introduce-creator") + fun getIntroduceCreator( + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?, + pageable: Pageable + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.getIntroduceCreator( + member, + offset = pageable.offset, + limit = pageable.pageSize.toLong() + ) + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt index 8debfd6..49e1571 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt @@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.content.main.tab.free import kr.co.vividnext.sodalive.content.AudioContentRepository import kr.co.vividnext.sodalive.content.ContentType +import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem 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.GetContentCurationResponse @@ -89,4 +90,27 @@ class AudioContentMainTabFreeService( curationList = curationList ) } + + fun getIntroduceCreator(member: Member, offset: Long, limit: Long): List { + val isAdult = member.auth != null + val memberId = member.id!! + + val introduceCreatorCuration = curationRepository.findByContentMainTabIdAndTitle( + tabId = 7L, + title = "크리에이터 소개", + isAdult = isAdult + ) + + return if (introduceCreatorCuration.isNotEmpty()) { + contentRepository.findAudioContentByCurationIdV2( + curationId = introduceCreatorCuration[0].id!!, + memberId = memberId, + isAdult = isAdult, + offset = offset, + limit = limit + ) + } else { + emptyList() + } + } } From e1bfd944e98001381d50d239c49e7065678c46e9 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 14 Feb 2025 15:44:40 +0900 Subject: [PATCH 23/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=AC=B4=EB=A3=8C=20=ED=83=AD=20-=20=EC=83=88?= =?UTF-8?q?=EB=A1=9C=EC=9A=B4=20=EC=BD=98=ED=85=90=EC=B8=A0=20=ED=85=8C?= =?UTF-8?q?=EB=A7=88=20=EC=84=A0=ED=83=9D=20=EC=95=A1=EC=85=98=20API=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../free/AudioContentMainTabFreeController.kt | 24 +++++++++++++++++++ .../free/AudioContentMainTabFreeService.kt | 19 +++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeController.kt index d92a08a..4c8fa63 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeController.kt @@ -2,11 +2,13 @@ package kr.co.vividnext.sodalive.content.main.tab.free 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 import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RestController @RestController @@ -36,4 +38,26 @@ class AudioContentMainTabFreeController(private val service: AudioContentMainTab ) ) } + + @GetMapping("/new-content-by-theme") + fun getNewContentByTheme( + @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 { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.getNewContentByTheme( + theme, + isAdultContentVisible = isAdultContentVisible ?: true, + contentType = contentType ?: ContentType.ALL, + member, + offset = pageable.offset, + limit = pageable.pageSize.toLong() + ) + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt index 49e1571..df99edc 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/free/AudioContentMainTabFreeService.kt @@ -113,4 +113,23 @@ class AudioContentMainTabFreeService( emptyList() } } + + fun getNewContentByTheme( + theme: String, + isAdultContentVisible: Boolean, + contentType: ContentType, + member: Member, + offset: Long, + limit: Long + ): List { + return audioContentRepository.findByTheme( + memberId = member.id!!, + theme = theme, + isAdult = member.auth != null && isAdultContentVisible, + contentType = contentType, + offset = offset, + limit = limit, + isFree = true + ) + } } From 713d42a67453b676b62c1bef54661596f5ffbcbe Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 14 Feb 2025 15:55:21 +0900 Subject: [PATCH 24/26] =?UTF-8?q?=EC=83=88=EB=A1=9C=EC=9A=B4=20=EC=BD=98?= =?UTF-8?q?=ED=85=90=EC=B8=A0=20=EC=A0=84=EC=B2=B4=EB=B3=B4=EA=B8=B0=20-?= =?UTF-8?q?=20=EB=AC=B4=EB=A3=8C=20=EC=BD=98=ED=85=90=EC=B8=A0=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=EB=B3=B4=EA=B8=B0=EB=A5=BC=20=EC=9C=84=ED=95=B4=20isF?= =?UTF-8?q?ree=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/content/AudioContentRepository.kt | 12 ++++++++++++ .../content/main/AudioContentMainController.kt | 2 ++ .../sodalive/content/main/AudioContentMainService.kt | 3 +++ 3 files changed, 17 insertions(+) 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 6451801..eacea2a 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt @@ -81,6 +81,7 @@ interface AudioContentQueryRepository { ): Int fun findByThemeFor2Weeks( + isFree: Boolean = false, cloudfrontHost: String, memberId: Long, theme: String = "", @@ -91,6 +92,7 @@ interface AudioContentQueryRepository { ): List fun totalCountNewContentFor2Weeks( + isFree: Boolean = false, theme: String, memberId: Long, isAdult: Boolean, @@ -456,6 +458,7 @@ class AudioContentQueryRepositoryImpl( } override fun totalCountNewContentFor2Weeks( + isFree: Boolean, theme: String, memberId: Long, isAdult: Boolean, @@ -484,6 +487,10 @@ class AudioContentQueryRepositoryImpl( where = where.and(audioContentTheme.theme.eq(theme)) } + if (isFree) { + where = where.and(audioContent.price.loe(0)) + } + return queryFactory .select(audioContent.id) .from(audioContent) @@ -495,6 +502,7 @@ class AudioContentQueryRepositoryImpl( } override fun findByThemeFor2Weeks( + isFree: Boolean, cloudfrontHost: String, memberId: Long, theme: String, @@ -526,6 +534,10 @@ class AudioContentQueryRepositoryImpl( where = where.and(audioContentTheme.theme.eq(theme)) } + if (isFree) { + where = where.and(audioContent.price.loe(0)) + } + return queryFactory .select( QGetAudioContentMainItem( diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainController.kt index c1fc22d..de06c18 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainController.kt @@ -92,6 +92,7 @@ class AudioContentMainController( @GetMapping("/new/all") fun getNewContentAllByTheme( + @RequestParam("isFree", required = false) isFree: Boolean? = null, @RequestParam("theme") theme: String, @RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null, @RequestParam("contentType", required = false) contentType: ContentType? = null, @@ -102,6 +103,7 @@ class AudioContentMainController( ApiResponse.ok( service.getNewContentFor2WeeksByTheme( + isFree = isFree ?: false, theme = theme, isAdultContentVisible = isAdultContentVisible ?: true, contentType = contentType ?: ContentType.ALL, 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 b72b829..faabf41 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 @@ -50,6 +50,7 @@ class AudioContentMainService( @Transactional(readOnly = true) fun getNewContentFor2WeeksByTheme( + isFree: Boolean, theme: String, isAdultContentVisible: Boolean, contentType: ContentType, @@ -57,12 +58,14 @@ class AudioContentMainService( pageable: Pageable ): GetNewContentAllResponse { val totalCount = repository.totalCountNewContentFor2Weeks( + isFree, theme, memberId = member.id!!, isAdult = member.auth != null && isAdultContentVisible, contentType = contentType ) val items = repository.findByThemeFor2Weeks( + isFree, cloudfrontHost = imageHost, memberId = member.id!!, theme = theme, From 34452525d48ea4976c89eafbe320f3555a0b1a47 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 14 Feb 2025 22:00:13 +0900 Subject: [PATCH 25/26] =?UTF-8?q?=EB=AA=A8=EB=8B=9D=EC=BD=9C=20=EC=83=88?= =?UTF-8?q?=EB=A1=9C=EC=9A=B4=20=EC=BD=98=ED=85=90=EC=B8=A0=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=EB=B3=B4=EA=B8=B0=20-=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/AudioContentRepository.kt | 62 +++++++++++++++++++ .../AudioContentMainTabAlarmController.kt | 20 ++++++ .../alarm/AudioContentMainTabAlarmService.kt | 31 ++++++++-- 3 files changed, 109 insertions(+), 4 deletions(-) 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 eacea2a..d0e30dc 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt @@ -73,6 +73,14 @@ interface AudioContentQueryRepository { isFree: Boolean = false ): List + fun findAlarmContentByTheme( + memberId: Long, + theme: List, + isAdult: Boolean = false, + offset: Long = 0, + limit: Long = 20 + ): List + fun totalCountByTheme( memberId: Long, theme: String = "", @@ -424,6 +432,60 @@ class AudioContentQueryRepositoryImpl( .fetch() } + override fun findAlarmContentByTheme( + memberId: Long, + theme: List, + isAdult: Boolean, + 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 = listOf(audioContent.releaseDate.desc(), audioContent.id.desc()) + + var where = audioContent.isActive.isTrue + .and(audioContent.duration.isNotNull) + .and( + audioContent.releaseDate.isNull + .or(audioContent.releaseDate.loe(LocalDateTime.now())) + .or(audioContent.member.id.eq(memberId)) + ) + .and(blockMember.id.isNull) + + if (!isAdult) { + where = where.and(audioContent.isAdult.isFalse) + } + + if (theme.isNotEmpty()) { + where = where.and(audioContentTheme.theme.`in`(theme)) + } + + return queryFactory + .select( + QGetAudioContentMainItem( + audioContent.id, + audioContent.coverImage.prepend("/").prepend(imageHost), + audioContent.title, + member.id, + member.profileImage.prepend("/").prepend(imageHost), + member.nickname, + audioContent.price, + audioContent.duration + ) + ) + .from(audioContent) + .innerJoin(audioContent.member, member) + .innerJoin(audioContent.theme, audioContentTheme) + .leftJoin(blockMember).on(blockMemberCondition) + .where(where) + .offset(offset) + .limit(limit) + .orderBy(*orderBy.toTypedArray()) + .fetch() + } + override fun totalCountByTheme(memberId: Long, theme: String, isAdult: Boolean, contentType: ContentType): Int { var where = audioContent.isActive.isTrue .and(audioContent.duration.isNotNull) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmController.kt index 68bae3c..23b03bd 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmController.kt @@ -3,9 +3,11 @@ 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.member.Member +import org.springframework.data.domain.Pageable 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.RequestParam import org.springframework.web.bind.annotation.RestController @RestController @@ -19,4 +21,22 @@ class AudioContentMainTabAlarmController(private val service: AudioContentMainTa ApiResponse.ok(service.fetchData(member)) } + + @GetMapping("/all") + fun fetchAlarmContentByTheme( + @RequestParam("theme") theme: String, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?, + pageable: Pageable + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.fetchAlarmContentByTheme( + theme, + member, + offset = pageable.offset, + limit = pageable.pageSize.toLong() + ) + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmService.kt index a2bf598..bac8749 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/alarm/AudioContentMainTabAlarmService.kt @@ -1,7 +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.GetAudioContentMainItem 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.GetContentCurationResponse @@ -32,11 +32,10 @@ class AudioContentMainTabAlarmService( ) val alarmThemeList = listOf("모닝콜", "슬립콜", "알람") - val newAlarmContentList = contentRepository.findByTheme( + val newAlarmContentList = contentRepository.findAlarmContentByTheme( memberId = memberId, - theme = alarmThemeList[0], + theme = alarmThemeList, isAdult = isAdult, - contentType = ContentType.ALL, limit = 10 ) @@ -81,4 +80,28 @@ class AudioContentMainTabAlarmService( curationList = curationList ) } + + fun fetchAlarmContentByTheme( + theme: String, + member: Member, + offset: Long, + limit: Long + ): List { + val alarmThemeList = if (theme.isNotBlank()) { + listOf(theme) + } else { + listOf("모닝콜", "슬립콜", "알람") + } + + val memberId = member.id!! + val isAdult = member.auth != null + + return contentRepository.findAlarmContentByTheme( + memberId = memberId, + theme = alarmThemeList, + isAdult = isAdult, + offset = offset, + limit = limit + ) + } } From 3d1716d847b2d9dff81e33be7b0c73c8d1784123 Mon Sep 17 00:00:00 2001 From: Klaus Date: Sat, 15 Feb 2025 02:01:59 +0900 Subject: [PATCH 26/26] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=8B=A4=EC=8B=9C=EB=93=A3=EA=B8=B0,=20ASMR=20-=20?= =?UTF-8?q?=EC=B1=84=EB=84=90=EB=B3=84=20=EC=BD=98=ED=85=90=EC=B8=A0=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/tab/AudioContentMainTabRepository.kt | 62 +++++++++++++++++++ .../asmr/AudioContentMainTabAsmrController.kt | 16 +++++ .../asmr/AudioContentMainTabAsmrService.kt | 52 ++++++++++++++++ .../tab/asmr/GetContentMainTabAsmrResponse.kt | 4 ++ ...AudioContentMainTabLiveReplayController.kt | 16 +++++ .../AudioContentMainTabLiveReplayService.kt | 52 ++++++++++++++++ .../GetContentMainTabLiveReplayResponse.kt | 4 ++ .../sodalive/rank/RankingRepository.kt | 20 +++++- .../vividnext/sodalive/rank/RankingService.kt | 16 +++-- 9 files changed, 236 insertions(+), 6 deletions(-) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt new file mode 100644 index 0000000..a5ef40a --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/AudioContentMainTabRepository.kt @@ -0,0 +1,62 @@ +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.QAudioContent.audioContent +import kr.co.vividnext.sodalive.content.main.ContentCreatorResponse +import kr.co.vividnext.sodalive.content.main.QContentCreatorResponse +import kr.co.vividnext.sodalive.content.theme.QAudioContentTheme.audioContentTheme +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.stereotype.Repository + +@Repository +class AudioContentMainTabRepository( + private val queryFactory: JPAQueryFactory, + + @Value("\${cloud.aws.cloud-front.host}") + private val imageHost: String +) { + fun findCreatorByThemeContent( + memberId: Long, + theme: String, + minCount: Int + ): List { + val blockMemberCondition = blockMember.member.id.eq(member.id) + .and(blockMember.isActive.isTrue) + .and(blockMember.blockedMember.id.eq(memberId)) + + val where = member.isActive.isTrue + .and(member.role.eq(MemberRole.CREATOR)) + .and(audioContent.isActive.isTrue) + .and(audioContent.duration.isNotNull) + .and(audioContent.limited.isNull) + .and(audioContentTheme.isActive.isTrue) + .and(audioContentTheme.theme.eq(theme)) + .and(blockMember.id.isNull) + + return queryFactory + .select( + QContentCreatorResponse( + member.id, + member.nickname, + member.profileImage.prepend("/").prepend(imageHost) + ) + ) + .from(member) + .innerJoin(audioContent).on(member.id.eq(audioContent.member.id)) + .innerJoin(audioContent.theme, audioContentTheme) + .leftJoin(blockMember).on(blockMemberCondition) + .where(where) + .groupBy(member.id) + .having(audioContent.id.count().goe(minCount)) + .orderBy( + Expressions.numberTemplate(Double::class.java, "function('rand')").asc() + ) + .offset(0) + .limit(20) + .fetch() + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrController.kt index ad35a6d..7714934 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrController.kt @@ -6,6 +6,7 @@ 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.RequestParam import org.springframework.web.bind.annotation.RestController @RestController @@ -19,4 +20,19 @@ class AudioContentMainTabAsmrController(private val service: AudioContentMainTab ApiResponse.ok(service.fetchData(member)) } + + @GetMapping("/popular-content-by-creator") + fun getPopularContentByCreator( + @RequestParam creatorId: Long, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.getPopularContentByCreator( + creatorId = creatorId, + isAdult = member.auth != null + ) + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt index a8bcde8..4ac40c4 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/AudioContentMainTabAsmrService.kt @@ -4,7 +4,9 @@ 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.main.curation.AudioContentCurationQueryRepository +import kr.co.vividnext.sodalive.content.main.tab.AudioContentMainTabRepository import kr.co.vividnext.sodalive.content.main.tab.GetContentCurationResponse +import kr.co.vividnext.sodalive.content.main.tab.GetPopularContentByCreatorResponse import kr.co.vividnext.sodalive.event.EventService import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.rank.RankingService @@ -15,6 +17,7 @@ import java.time.temporal.TemporalAdjusters @Service class AudioContentMainTabAsmrService( + private val repository: AudioContentMainTabRepository, private val bannerService: AudioContentBannerService, private val contentRepository: AudioContentRepository, private val rankingService: RankingService, @@ -59,6 +62,32 @@ class AudioContentMainTabAsmrService( theme = theme ) + val creatorList = repository.findCreatorByThemeContent( + memberId = memberId, + theme = theme, + minCount = 4 + ) + + val salesRankContentList = if (creatorList.isNotEmpty()) { + rankingService.fetchCreatorContentBySalesTop2( + creatorId = creatorList[0].creatorId, + isAdult = isAdult, + theme = theme + ) + } else { + emptyList() + } + + val salesCountRankContentList = if (creatorList.isNotEmpty()) { + rankingService.fetchCreatorContentBySalesCountTop2( + creatorId = creatorList[0].creatorId, + isAdult = isAdult, + theme = theme + ) + } else { + emptyList() + } + val eventBannerList = eventService.getEventList(isAdult = isAdult) val curationList = curationRepository.findByContentMainTabId(tabId = tabId, isAdult = isAdult) @@ -77,8 +106,31 @@ class AudioContentMainTabAsmrService( contentBannerList = contentBannerList, newAsmrContentList = newAsmrContentList, rankAsmrContentList = rankAsmrContentList, + creatorList = creatorList, + salesRankContentList = salesRankContentList, + salesCountRankContentList = salesCountRankContentList, eventBannerList = eventBannerList, curationList = curationList ) } + + fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): GetPopularContentByCreatorResponse { + val theme = "ASMR" + val salesRankContentList = rankingService.fetchCreatorContentBySalesTop2( + creatorId = creatorId, + isAdult = isAdult, + theme = theme + ) + + val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop2( + creatorId = creatorId, + isAdult = isAdult, + theme = theme + ) + + return GetPopularContentByCreatorResponse( + salesRankContentList = salesRankContentList, + salesCountRankContentList = salesCountRankContentList + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/GetContentMainTabAsmrResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/GetContentMainTabAsmrResponse.kt index 5b406e1..9162e40 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/GetContentMainTabAsmrResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/asmr/GetContentMainTabAsmrResponse.kt @@ -1,5 +1,6 @@ package kr.co.vividnext.sodalive.content.main.tab.asmr +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 @@ -11,6 +12,9 @@ data class GetContentMainTabAsmrResponse( val contentBannerList: List, val newAsmrContentList: List, val rankAsmrContentList: List, + val creatorList: List, + val salesRankContentList: List, + val salesCountRankContentList: List, val eventBannerList: GetEventResponse, val curationList: List ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayController.kt index c9b3739..17b7e38 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayController.kt @@ -6,6 +6,7 @@ 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.RequestParam import org.springframework.web.bind.annotation.RestController @RestController @@ -19,4 +20,19 @@ class AudioContentMainTabLiveReplayController(private val service: AudioContentM ApiResponse.ok(service.fetchData(member)) } + + @GetMapping("/popular-content-by-creator") + fun getPopularContentByCreator( + @RequestParam creatorId: Long, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.getPopularContentByCreator( + creatorId = creatorId, + isAdult = member.auth != null + ) + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt index 767a8c9..d6d1164 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/AudioContentMainTabLiveReplayService.kt @@ -4,7 +4,9 @@ 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.main.curation.AudioContentCurationQueryRepository +import kr.co.vividnext.sodalive.content.main.tab.AudioContentMainTabRepository import kr.co.vividnext.sodalive.content.main.tab.GetContentCurationResponse +import kr.co.vividnext.sodalive.content.main.tab.GetPopularContentByCreatorResponse import kr.co.vividnext.sodalive.event.EventService import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.rank.RankingService @@ -15,6 +17,7 @@ import java.time.temporal.TemporalAdjusters @Service class AudioContentMainTabLiveReplayService( + private val repository: AudioContentMainTabRepository, private val bannerService: AudioContentBannerService, private val contentRepository: AudioContentRepository, private val rankingService: RankingService, @@ -59,6 +62,32 @@ class AudioContentMainTabLiveReplayService( theme = theme ) + val creatorList = repository.findCreatorByThemeContent( + memberId = memberId, + theme = theme, + minCount = 4 + ) + + val salesRankContentList = if (creatorList.isNotEmpty()) { + rankingService.fetchCreatorContentBySalesTop2( + creatorId = creatorList[0].creatorId, + isAdult = isAdult, + theme = theme + ) + } else { + emptyList() + } + + val salesCountRankContentList = if (creatorList.isNotEmpty()) { + rankingService.fetchCreatorContentBySalesCountTop2( + creatorId = creatorList[0].creatorId, + isAdult = isAdult, + theme = theme + ) + } else { + emptyList() + } + val eventBannerList = eventService.getEventList(isAdult = isAdult) val curationList = curationRepository.findByContentMainTabId(tabId = tabId, isAdult = isAdult) @@ -77,8 +106,31 @@ class AudioContentMainTabLiveReplayService( contentBannerList = contentBannerList, newLiveReplayContentList = newLiveReplayContentList, rankLiveReplayContentList = rankLiveReplayContentList, + creatorList = creatorList, + salesRankContentList = salesRankContentList, + salesCountRankContentList = salesCountRankContentList, eventBannerList = eventBannerList, curationList = curationList ) } + + fun getPopularContentByCreator(creatorId: Long, isAdult: Boolean): GetPopularContentByCreatorResponse { + val theme = "다시듣기" + val salesRankContentList = rankingService.fetchCreatorContentBySalesTop2( + creatorId = creatorId, + isAdult = isAdult, + theme = theme + ) + + val salesCountRankContentList = rankingService.fetchCreatorContentBySalesCountTop2( + creatorId = creatorId, + isAdult = isAdult, + theme = theme + ) + + return GetPopularContentByCreatorResponse( + salesRankContentList = salesRankContentList, + salesCountRankContentList = salesCountRankContentList + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/GetContentMainTabLiveReplayResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/GetContentMainTabLiveReplayResponse.kt index eea8309..05860b2 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/GetContentMainTabLiveReplayResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/tab/replay/GetContentMainTabLiveReplayResponse.kt @@ -1,5 +1,6 @@ package kr.co.vividnext.sodalive.content.main.tab.replay +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 @@ -11,6 +12,9 @@ data class GetContentMainTabLiveReplayResponse( val contentBannerList: List, val newLiveReplayContentList: List, val rankLiveReplayContentList: List, + val creatorList: List, + val salesRankContentList: List, + val salesCountRankContentList: List, val eventBannerList: GetEventResponse, val curationList: List ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt index cf804a5..c0e9c65 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingRepository.kt @@ -381,7 +381,11 @@ class RankingRepository( .fetch() } - fun fetchCreatorContentBySalesTop2(creatorId: Long, isAdult: Boolean): List { + fun fetchCreatorContentBySalesTop2( + creatorId: Long, + isAdult: Boolean, + theme: String + ): List { var where = member.isActive.isTrue .and(member.role.eq(MemberRole.CREATOR)) .and(audioContent.isActive.isTrue) @@ -395,6 +399,10 @@ class RankingRepository( where = where.and(series.isAdult.isFalse) } + if (theme.isNotBlank()) { + where = where.and(audioContentTheme.theme.eq(theme)) + } + return queryFactory .select( QGetAudioContentRankingItem( @@ -421,7 +429,11 @@ class RankingRepository( .fetch() } - fun fetchCreatorContentBySalesCountTop2(creatorId: Long, isAdult: Boolean): List { + fun fetchCreatorContentBySalesCountTop2( + creatorId: Long, + isAdult: Boolean, + theme: String + ): List { var where = member.isActive.isTrue .and(member.role.eq(MemberRole.CREATOR)) .and(audioContent.isActive.isTrue) @@ -435,6 +447,10 @@ class RankingRepository( where = where.and(series.isAdult.isFalse) } + if (theme.isNotBlank()) { + where = where.and(audioContentTheme.theme.eq(theme)) + } + return queryFactory .select( QGetAudioContentRankingItem( diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt index f9aac15..5f657d0 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/rank/RankingService.kt @@ -189,12 +189,20 @@ class RankingService( return repository.fetchCreatorByContentRevenueRankTop20(memberId, startDate, endDate) } - fun fetchCreatorContentBySalesTop2(creatorId: Long, isAdult: Boolean): List { - return repository.fetchCreatorContentBySalesTop2(creatorId, isAdult) + fun fetchCreatorContentBySalesTop2( + creatorId: Long, + isAdult: Boolean, + theme: String = "" + ): List { + return repository.fetchCreatorContentBySalesTop2(creatorId, isAdult, theme) } - fun fetchCreatorContentBySalesCountTop2(creatorId: Long, isAdult: Boolean): List { - return repository.fetchCreatorContentBySalesCountTop2(creatorId, isAdult) + fun fetchCreatorContentBySalesCountTop2( + creatorId: Long, + isAdult: Boolean, + theme: String = "" + ): List { + return repository.fetchCreatorContentBySalesCountTop2(creatorId, isAdult, theme) } fun fetchCreatorBySeriesRevenueRankTop20(