feat(audio-recommendation): 추천 조회 언어를 전달한다

This commit is contained in:
2026-09-09 23:19:38 +09:00
parent ee3dfc40d9
commit 44008c7623
3 changed files with 58 additions and 19 deletions
@@ -1,6 +1,7 @@
package kr.co.vividnext.sodalive.v2.content.recommendation.application package kr.co.vividnext.sodalive.v2.content.recommendation.application
import kr.co.vividnext.sodalive.i18n.Lang import kr.co.vividnext.sodalive.i18n.Lang
import kr.co.vividnext.sodalive.i18n.LangContext
import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.member.Member
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
import kr.co.vividnext.sodalive.v2.content.recommendation.domain.AudioCard import kr.co.vividnext.sodalive.v2.content.recommendation.domain.AudioCard
@@ -17,7 +18,8 @@ import java.time.ZoneId
class AudioRecommendationQueryService( class AudioRecommendationQueryService(
private val queryPort: AudioRecommendationQueryPort, private val queryPort: AudioRecommendationQueryPort,
private val memberContentPreferenceService: MemberContentPreferenceService, private val memberContentPreferenceService: MemberContentPreferenceService,
private val snapshotFallbackService: AudioRecommendationSnapshotFallbackService private val snapshotFallbackService: AudioRecommendationSnapshotFallbackService,
private val langContext: LangContext
) { ) {
fun getRecommendations(member: Member?): AudioRecommendations { fun getRecommendations(member: Member?): AudioRecommendations {
val now = LocalDateTime.now() val now = LocalDateTime.now()
@@ -25,6 +27,7 @@ class AudioRecommendationQueryService(
val canViewAdultContent = canViewAdultContent(member) val canViewAdultContent = canViewAdultContent(member)
val visibility = if (canViewAdultContent) AudioRecommendationVisibility.ALL else AudioRecommendationVisibility.SAFE val visibility = if (canViewAdultContent) AudioRecommendationVisibility.ALL else AudioRecommendationVisibility.SAFE
val memberId = member?.id val memberId = member?.id
val locale = langContext.lang.code
val bannerLang = if (memberContentPreferenceService.resolveCountryCode(member) == "JP") Lang.JA else Lang.KO val bannerLang = if (memberContentPreferenceService.resolveCountryCode(member) == "JP") Lang.JA else Lang.KO
val newAndHotSectionType = newAndHotSectionType(visibility) val newAndHotSectionType = newAndHotSectionType(visibility)
val mostCommentedSectionType = mostCommentedSectionType(visibility) val mostCommentedSectionType = mostCommentedSectionType(visibility)
@@ -48,25 +51,28 @@ class AudioRecommendationQueryService(
return AudioRecommendations( return AudioRecommendations(
banners = queryPort.findBanners(BANNER_LIMIT, memberId, canViewAdultContent, bannerLang), banners = queryPort.findBanners(BANNER_LIMIT, memberId, canViewAdultContent, bannerLang),
originalSeries = queryPort.findOriginalSeries(ORIGINAL_SERIES_LIMIT, memberId, canViewAdultContent, now), originalSeries = queryPort.findOriginalSeries(ORIGINAL_SERIES_LIMIT, memberId, canViewAdultContent, now),
latestAudios = queryPort.findLatestAudios(LATEST_AUDIO_LIMIT, memberId, canViewAdultContent, now), latestAudios = queryPort.findLatestAudios(LATEST_AUDIO_LIMIT, memberId, canViewAdultContent, now, locale),
newAndHotAudios = queryPort.findAudioCardsByIds( newAndHotAudios = queryPort.findAudioCardsByIds(
newAndHotSnapshots.map { it.targetId }, newAndHotSnapshots.map { it.targetId },
memberId, memberId,
canViewAdultContent, canViewAdultContent,
now now,
locale
), ),
freeAudios = queryPort.findFreeAudios(FREE_AUDIO_LIMIT, memberId, canViewAdultContent, now), freeAudios = queryPort.findFreeAudios(FREE_AUDIO_LIMIT, memberId, canViewAdultContent, now, locale),
pointAudios = queryPort.findPointAudios(POINT_AUDIO_LIMIT, memberId, canViewAdultContent, now), pointAudios = queryPort.findPointAudios(POINT_AUDIO_LIMIT, memberId, canViewAdultContent, now, locale),
mostCommentedAudios = queryPort.findCommentedAudiosByIds( mostCommentedAudios = queryPort.findCommentedAudiosByIds(
mostCommentedSnapshots.map { it.targetId }, mostCommentedSnapshots.map { it.targetId },
memberId, memberId,
canViewAdultContent canViewAdultContent,
locale
), ),
recommendedAudios = queryPort.findAudioCardsByIds( recommendedAudios = queryPort.findAudioCardsByIds(
recommendedSnapshots.map { it.targetId }, recommendedSnapshots.map { it.targetId },
memberId, memberId,
canViewAdultContent, canViewAdultContent,
now now,
locale
) )
) )
} }
@@ -83,7 +89,8 @@ class AudioRecommendationQueryService(
snapshots.map { it.targetId }, snapshots.map { it.targetId },
member.id, member.id,
canViewAdultContent, canViewAdultContent,
now now,
langContext.lang.code
) )
} }
@@ -17,16 +17,40 @@ interface AudioRecommendationQueryPort {
lang: Lang = Lang.KO lang: Lang = Lang.KO
): List<RecommendationBanner> ): List<RecommendationBanner>
fun findOriginalSeries(limit: Int, memberId: Long?, canViewAdultContent: Boolean, now: LocalDateTime): List<OriginalSeries> fun findOriginalSeries(limit: Int, memberId: Long?, canViewAdultContent: Boolean, now: LocalDateTime): List<OriginalSeries>
fun findLatestAudios(limit: Int, memberId: Long?, canViewAdultContent: Boolean, now: LocalDateTime): List<AudioCard> fun findLatestAudios(
fun findFreeAudios(limit: Int, memberId: Long?, canViewAdultContent: Boolean, now: LocalDateTime): List<AudioCard> limit: Int,
fun findPointAudios(limit: Int, memberId: Long?, canViewAdultContent: Boolean, now: LocalDateTime): List<AudioCard> memberId: Long?,
canViewAdultContent: Boolean,
now: LocalDateTime,
locale: String
): List<AudioCard>
fun findFreeAudios(
limit: Int,
memberId: Long?,
canViewAdultContent: Boolean,
now: LocalDateTime,
locale: String
): List<AudioCard>
fun findPointAudios(
limit: Int,
memberId: Long?,
canViewAdultContent: Boolean,
now: LocalDateTime,
locale: String
): List<AudioCard>
fun findAudioCardsByIds( fun findAudioCardsByIds(
contentIds: List<Long>, contentIds: List<Long>,
memberId: Long?, memberId: Long?,
canViewAdultContent: Boolean, canViewAdultContent: Boolean,
now: LocalDateTime now: LocalDateTime,
locale: String
): List<AudioCard> ): List<AudioCard>
fun findCommentedAudiosByIds(contentIds: List<Long>, memberId: Long?, canViewAdultContent: Boolean): List<CommentedAudio> fun findCommentedAudiosByIds(
contentIds: List<Long>,
memberId: Long?,
canViewAdultContent: Boolean,
locale: String
): List<CommentedAudio>
fun findNewAndHotSnapshots( fun findNewAndHotSnapshots(
windowStart: LocalDateTime, windowStart: LocalDateTime,
snapshotAt: LocalDateTime, snapshotAt: LocalDateTime,
@@ -1,6 +1,7 @@
package kr.co.vividnext.sodalive.v2.content.recommendation.application package kr.co.vividnext.sodalive.v2.content.recommendation.application
import kr.co.vividnext.sodalive.i18n.Lang import kr.co.vividnext.sodalive.i18n.Lang
import kr.co.vividnext.sodalive.i18n.LangContext
import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.member.Member
import kr.co.vividnext.sodalive.member.MemberRole import kr.co.vividnext.sodalive.member.MemberRole
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
@@ -19,10 +20,12 @@ class AudioRecommendationQueryServiceTest {
private val queryPort = Mockito.mock(AudioRecommendationQueryPort::class.java) private val queryPort = Mockito.mock(AudioRecommendationQueryPort::class.java)
private val preferenceService = Mockito.mock(MemberContentPreferenceService::class.java) private val preferenceService = Mockito.mock(MemberContentPreferenceService::class.java)
private val fallbackService = Mockito.mock(AudioRecommendationSnapshotFallbackService::class.java) private val fallbackService = Mockito.mock(AudioRecommendationSnapshotFallbackService::class.java)
private val langContext = LangContext().apply { setLang(Lang.EN) }
private val service = AudioRecommendationQueryService( private val service = AudioRecommendationQueryService(
queryPort, queryPort,
preferenceService, preferenceService,
fallbackService fallbackService,
langContext
) )
@Test @Test
@@ -83,25 +86,29 @@ class AudioRecommendationQueryServiceTest {
eqValue(AudioRecommendationQueryService.LATEST_AUDIO_LIMIT), eqValue(AudioRecommendationQueryService.LATEST_AUDIO_LIMIT),
Mockito.isNull(), Mockito.isNull(),
eqValue(false), eqValue(false),
anyLocalDateTime() anyLocalDateTime(),
eqValue(Lang.EN.code)
) )
Mockito.verify(queryPort).findFreeAudios( Mockito.verify(queryPort).findFreeAudios(
eqValue(AudioRecommendationQueryService.FREE_AUDIO_LIMIT), eqValue(AudioRecommendationQueryService.FREE_AUDIO_LIMIT),
Mockito.isNull(), Mockito.isNull(),
eqValue(false), eqValue(false),
anyLocalDateTime() anyLocalDateTime(),
eqValue(Lang.EN.code)
) )
Mockito.verify(queryPort).findPointAudios( Mockito.verify(queryPort).findPointAudios(
eqValue(AudioRecommendationQueryService.POINT_AUDIO_LIMIT), eqValue(AudioRecommendationQueryService.POINT_AUDIO_LIMIT),
Mockito.isNull(), Mockito.isNull(),
eqValue(false), eqValue(false),
anyLocalDateTime() anyLocalDateTime(),
eqValue(Lang.EN.code)
) )
Mockito.verify(queryPort).findAudioCardsByIds( Mockito.verify(queryPort).findAudioCardsByIds(
eqValue(listOf(1L)), eqValue(listOf(1L)),
Mockito.isNull(), Mockito.isNull(),
eqValue(false), eqValue(false),
anyLocalDateTime() anyLocalDateTime(),
eqValue(Lang.EN.code)
) )
} }
@@ -198,7 +205,8 @@ class AudioRecommendationQueryServiceTest {
eqValue(listOf(3L, 4L, 5L)), eqValue(listOf(3L, 4L, 5L)),
eqValue(member.id), eqValue(member.id),
eqValue(true), eqValue(true),
anyLocalDateTime() anyLocalDateTime(),
eqValue(Lang.EN.code)
) )
val result = service.findNewAndHotAudios(member, offset = 20L, limit = 21) val result = service.findNewAndHotAudios(member, offset = 20L, limit = 21)