Compare commits
2 Commits
13029ab8d2
...
dc0df81232
| Author | SHA1 | Date | |
|---|---|---|---|
| dc0df81232 | |||
| c0c61da44b |
@@ -21,6 +21,7 @@ import kr.co.vividnext.sodalive.content.order.OrderType
|
||||
import kr.co.vividnext.sodalive.content.pin.PinContent
|
||||
import kr.co.vividnext.sodalive.content.pin.PinContentRepository
|
||||
import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository
|
||||
import kr.co.vividnext.sodalive.content.theme.translation.ContentThemeTranslationRepository
|
||||
import kr.co.vividnext.sodalive.content.translation.ContentTranslation
|
||||
import kr.co.vividnext.sodalive.content.translation.ContentTranslationPayload
|
||||
import kr.co.vividnext.sodalive.content.translation.ContentTranslationRepository
|
||||
@@ -75,6 +76,8 @@ class AudioContentService(
|
||||
|
||||
private val langContext: LangContext,
|
||||
|
||||
private val contentThemeTranslationRepository: ContentThemeTranslationRepository,
|
||||
|
||||
@Value("\${cloud.aws.s3.content-bucket}")
|
||||
private val audioContentBucket: String,
|
||||
|
||||
@@ -1140,8 +1143,20 @@ class AudioContentService(
|
||||
orderByRandom: Boolean = false,
|
||||
isPointAvailableOnly: Boolean = false
|
||||
): List<AudioContentMainItem> {
|
||||
/**
|
||||
* - AS-IS theme은 한글만 처리하도록 되어 있음
|
||||
* - TO-BE 번역된 theme이 들어와도 동일한 동작을 하도록 처리
|
||||
*/
|
||||
val normalizedTheme = normalizeThemeForQuery(
|
||||
themes = theme,
|
||||
contentType = contentType,
|
||||
isFree = isFree,
|
||||
isAdult = isAdult,
|
||||
isPointAvailableOnly = isPointAvailableOnly
|
||||
)
|
||||
|
||||
val contentList = repository.getLatestContentByTheme(
|
||||
theme = theme,
|
||||
theme = normalizedTheme,
|
||||
contentType = contentType,
|
||||
offset = offset,
|
||||
limit = limit,
|
||||
@@ -1170,4 +1185,60 @@ class AudioContentService(
|
||||
contentList
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* theme 파라미터로 번역된 테마명이 들어와도 한글 원문 테마로 조회되도록 정규화한다.
|
||||
* - 현재 언어(locale)에 해당하는 테마 번역 목록을 활성 테마 집합과 매칭하여 역매핑한다.
|
||||
* - 입력이 이미 한글인 경우 그대로 유지한다.
|
||||
* - 매칭 실패 시 원본 값을 유지한다.
|
||||
*/
|
||||
private fun normalizeThemeForQuery(
|
||||
themes: List<String>,
|
||||
contentType: ContentType,
|
||||
isFree: Boolean,
|
||||
isAdult: Boolean,
|
||||
isPointAvailableOnly: Boolean
|
||||
): List<String> {
|
||||
if (themes.isEmpty()) return themes
|
||||
|
||||
val themesWithIds = themeQueryRepository.getActiveThemeWithIdsOfContent(
|
||||
isAdult = isAdult,
|
||||
isFree = isFree,
|
||||
isPointAvailableOnly = isPointAvailableOnly,
|
||||
contentType = contentType
|
||||
)
|
||||
|
||||
if (themesWithIds.isEmpty()) return themes
|
||||
|
||||
val idByKorean = themesWithIds.associate { it.theme to it.id }
|
||||
val koreanById = themesWithIds.associate { it.id to it.theme }
|
||||
|
||||
val locale = langContext.lang.code
|
||||
// 번역 테마를 역매핑하기 위해 현재 locale의 번역 목록을 조회
|
||||
val translatedByTextToId = run {
|
||||
val ids = themesWithIds.map { it.id }
|
||||
if (ids.isEmpty()) {
|
||||
emptyMap()
|
||||
} else {
|
||||
contentThemeTranslationRepository
|
||||
.findByContentThemeIdInAndLocale(ids, locale)
|
||||
.associate { it.theme to it.contentThemeId }
|
||||
}
|
||||
}
|
||||
|
||||
return themes.asSequence()
|
||||
.map { input ->
|
||||
when {
|
||||
idByKorean.containsKey(input) -> input // 이미 한글 원문
|
||||
translatedByTextToId.containsKey(input) -> {
|
||||
val id = translatedByTextToId[input]!!
|
||||
koreanById[id] ?: input
|
||||
}
|
||||
|
||||
else -> input
|
||||
}
|
||||
}
|
||||
.distinct()
|
||||
.toList()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import kr.co.vividnext.sodalive.content.main.banner.AudioContentBannerType
|
||||
import kr.co.vividnext.sodalive.content.main.banner.GetAudioContentBannerResponse
|
||||
import kr.co.vividnext.sodalive.content.main.curation.GetAudioContentCurationResponse
|
||||
import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository
|
||||
import kr.co.vividnext.sodalive.content.theme.AudioContentThemeService
|
||||
import kr.co.vividnext.sodalive.content.theme.translation.ContentThemeTranslationRepository
|
||||
import kr.co.vividnext.sodalive.content.translation.ContentTranslationRepository
|
||||
import kr.co.vividnext.sodalive.event.EventItem
|
||||
import kr.co.vividnext.sodalive.i18n.LangContext
|
||||
@@ -22,6 +24,9 @@ class AudioContentMainService(
|
||||
private val repository: AudioContentRepository,
|
||||
private val blockMemberRepository: BlockMemberRepository,
|
||||
private val audioContentThemeRepository: AudioContentThemeQueryRepository,
|
||||
private val audioContentThemeService: AudioContentThemeService,
|
||||
|
||||
private val contentThemeTranslationRepository: ContentThemeTranslationRepository,
|
||||
|
||||
private val contentTranslationRepository: ContentTranslationRepository,
|
||||
|
||||
@@ -31,9 +36,21 @@ class AudioContentMainService(
|
||||
private val imageHost: String
|
||||
) {
|
||||
@Transactional(readOnly = true)
|
||||
@Cacheable(cacheNames = ["default"], key = "'themeList:' + ':' + #isAdult")
|
||||
fun getThemeList(isAdult: Boolean, contentType: ContentType): List<String> {
|
||||
return audioContentThemeRepository.getActiveThemeOfContent(isAdult = isAdult, contentType = contentType)
|
||||
/**
|
||||
* 콘텐츠 테마 조회
|
||||
*
|
||||
* - langContext에 따라 기본 한국어 데이터 혹은 번역된 콘텐츠 테마를 조회해야 함
|
||||
*
|
||||
* - 번역된 테마 데이터가 없다면 번역하여 반환
|
||||
* - 번역된 데이터가 있다면 번역된 데이터를 조회하여 반환
|
||||
*/
|
||||
// 표시용 테마 목록은 언어 컨텍스트에 따라 번역된 값을 반환해야 한다.
|
||||
// AudioContentThemeService가 번역/저장을 처리하므로 이를 사용한다.
|
||||
return audioContentThemeService.getActiveThemeOfContent(
|
||||
isAdult = isAdult,
|
||||
contentType = contentType
|
||||
)
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@@ -66,8 +83,12 @@ class AudioContentMainService(
|
||||
member: Member,
|
||||
pageable: Pageable
|
||||
): GetNewContentAllResponse {
|
||||
/**
|
||||
* - AS-IS theme은 한글만 처리하도록 되어 있음
|
||||
* - TO-BE 번역된 theme이 들어와도 동일한 동작을 하도록 처리
|
||||
*/
|
||||
val isAdult = member.auth != null && isAdultContentVisible
|
||||
val themeList = if (theme.isBlank()) {
|
||||
val themeListRaw = if (theme.isBlank()) {
|
||||
audioContentThemeRepository.getActiveThemeOfContent(
|
||||
isAdult = isAdult,
|
||||
contentType = contentType
|
||||
@@ -76,6 +97,12 @@ class AudioContentMainService(
|
||||
listOf(theme)
|
||||
}
|
||||
|
||||
val themeList = normalizeThemeForQuery(
|
||||
themes = themeListRaw,
|
||||
contentType = contentType,
|
||||
isAdult = isAdult
|
||||
)
|
||||
|
||||
val totalCount = repository.totalCountNewContentFor2Weeks(
|
||||
themeList,
|
||||
memberId = member.id!!,
|
||||
@@ -114,6 +141,56 @@ class AudioContentMainService(
|
||||
return GetNewContentAllResponse(totalCount, translatedContentList)
|
||||
}
|
||||
|
||||
/**
|
||||
* 번역된 테마명이 들어와도 한글 원문 테마로 조회되도록 정규화한다.
|
||||
*/
|
||||
private fun normalizeThemeForQuery(
|
||||
themes: List<String>,
|
||||
contentType: ContentType,
|
||||
isAdult: Boolean
|
||||
): List<String> {
|
||||
if (themes.isEmpty()) return themes
|
||||
|
||||
val themesWithIds = audioContentThemeRepository.getActiveThemeWithIdsOfContent(
|
||||
isAdult = isAdult,
|
||||
isFree = false,
|
||||
isPointAvailableOnly = false,
|
||||
contentType = contentType
|
||||
)
|
||||
|
||||
if (themesWithIds.isEmpty()) return themes
|
||||
|
||||
val idByKorean = themesWithIds.associate { it.theme to it.id }
|
||||
val koreanById = themesWithIds.associate { it.id to it.theme }
|
||||
|
||||
val locale = langContext.lang.code
|
||||
val translatedByTextToId = run {
|
||||
val ids = themesWithIds.map { it.id }
|
||||
if (ids.isEmpty()) {
|
||||
emptyMap()
|
||||
} else {
|
||||
contentThemeTranslationRepository
|
||||
.findByContentThemeIdInAndLocale(ids, locale)
|
||||
.associate { it.theme to it.contentThemeId }
|
||||
}
|
||||
}
|
||||
|
||||
return themes.asSequence()
|
||||
.map { input ->
|
||||
when {
|
||||
idByKorean.containsKey(input) -> input
|
||||
translatedByTextToId.containsKey(input) -> {
|
||||
val id = translatedByTextToId[input]!!
|
||||
koreanById[id] ?: input
|
||||
}
|
||||
|
||||
else -> input
|
||||
}
|
||||
}
|
||||
.distinct()
|
||||
.toList()
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@Cacheable(cacheNames = ["default"], key = "'newContentUploadCreatorList:' + #memberId + ':' + #isAdult")
|
||||
fun getNewContentUploadCreatorList(memberId: Long, isAdult: Boolean): List<ContentCreatorResponse> {
|
||||
|
||||
Reference in New Issue
Block a user