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.PinContent
|
||||||
import kr.co.vividnext.sodalive.content.pin.PinContentRepository
|
import kr.co.vividnext.sodalive.content.pin.PinContentRepository
|
||||||
import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository
|
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.ContentTranslation
|
||||||
import kr.co.vividnext.sodalive.content.translation.ContentTranslationPayload
|
import kr.co.vividnext.sodalive.content.translation.ContentTranslationPayload
|
||||||
import kr.co.vividnext.sodalive.content.translation.ContentTranslationRepository
|
import kr.co.vividnext.sodalive.content.translation.ContentTranslationRepository
|
||||||
@@ -75,6 +76,8 @@ class AudioContentService(
|
|||||||
|
|
||||||
private val langContext: LangContext,
|
private val langContext: LangContext,
|
||||||
|
|
||||||
|
private val contentThemeTranslationRepository: ContentThemeTranslationRepository,
|
||||||
|
|
||||||
@Value("\${cloud.aws.s3.content-bucket}")
|
@Value("\${cloud.aws.s3.content-bucket}")
|
||||||
private val audioContentBucket: String,
|
private val audioContentBucket: String,
|
||||||
|
|
||||||
@@ -1140,8 +1143,20 @@ class AudioContentService(
|
|||||||
orderByRandom: Boolean = false,
|
orderByRandom: Boolean = false,
|
||||||
isPointAvailableOnly: Boolean = false
|
isPointAvailableOnly: Boolean = false
|
||||||
): List<AudioContentMainItem> {
|
): 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(
|
val contentList = repository.getLatestContentByTheme(
|
||||||
theme = theme,
|
theme = normalizedTheme,
|
||||||
contentType = contentType,
|
contentType = contentType,
|
||||||
offset = offset,
|
offset = offset,
|
||||||
limit = limit,
|
limit = limit,
|
||||||
@@ -1170,4 +1185,60 @@ class AudioContentService(
|
|||||||
contentList
|
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.banner.GetAudioContentBannerResponse
|
||||||
import kr.co.vividnext.sodalive.content.main.curation.GetAudioContentCurationResponse
|
import kr.co.vividnext.sodalive.content.main.curation.GetAudioContentCurationResponse
|
||||||
import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository
|
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.content.translation.ContentTranslationRepository
|
||||||
import kr.co.vividnext.sodalive.event.EventItem
|
import kr.co.vividnext.sodalive.event.EventItem
|
||||||
import kr.co.vividnext.sodalive.i18n.LangContext
|
import kr.co.vividnext.sodalive.i18n.LangContext
|
||||||
@@ -22,6 +24,9 @@ class AudioContentMainService(
|
|||||||
private val repository: AudioContentRepository,
|
private val repository: AudioContentRepository,
|
||||||
private val blockMemberRepository: BlockMemberRepository,
|
private val blockMemberRepository: BlockMemberRepository,
|
||||||
private val audioContentThemeRepository: AudioContentThemeQueryRepository,
|
private val audioContentThemeRepository: AudioContentThemeQueryRepository,
|
||||||
|
private val audioContentThemeService: AudioContentThemeService,
|
||||||
|
|
||||||
|
private val contentThemeTranslationRepository: ContentThemeTranslationRepository,
|
||||||
|
|
||||||
private val contentTranslationRepository: ContentTranslationRepository,
|
private val contentTranslationRepository: ContentTranslationRepository,
|
||||||
|
|
||||||
@@ -31,9 +36,21 @@ class AudioContentMainService(
|
|||||||
private val imageHost: String
|
private val imageHost: String
|
||||||
) {
|
) {
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
@Cacheable(cacheNames = ["default"], key = "'themeList:' + ':' + #isAdult")
|
|
||||||
fun getThemeList(isAdult: Boolean, contentType: ContentType): List<String> {
|
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)
|
@Transactional(readOnly = true)
|
||||||
@@ -66,8 +83,12 @@ class AudioContentMainService(
|
|||||||
member: Member,
|
member: Member,
|
||||||
pageable: Pageable
|
pageable: Pageable
|
||||||
): GetNewContentAllResponse {
|
): GetNewContentAllResponse {
|
||||||
|
/**
|
||||||
|
* - AS-IS theme은 한글만 처리하도록 되어 있음
|
||||||
|
* - TO-BE 번역된 theme이 들어와도 동일한 동작을 하도록 처리
|
||||||
|
*/
|
||||||
val isAdult = member.auth != null && isAdultContentVisible
|
val isAdult = member.auth != null && isAdultContentVisible
|
||||||
val themeList = if (theme.isBlank()) {
|
val themeListRaw = if (theme.isBlank()) {
|
||||||
audioContentThemeRepository.getActiveThemeOfContent(
|
audioContentThemeRepository.getActiveThemeOfContent(
|
||||||
isAdult = isAdult,
|
isAdult = isAdult,
|
||||||
contentType = contentType
|
contentType = contentType
|
||||||
@@ -76,6 +97,12 @@ class AudioContentMainService(
|
|||||||
listOf(theme)
|
listOf(theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val themeList = normalizeThemeForQuery(
|
||||||
|
themes = themeListRaw,
|
||||||
|
contentType = contentType,
|
||||||
|
isAdult = isAdult
|
||||||
|
)
|
||||||
|
|
||||||
val totalCount = repository.totalCountNewContentFor2Weeks(
|
val totalCount = repository.totalCountNewContentFor2Weeks(
|
||||||
themeList,
|
themeList,
|
||||||
memberId = member.id!!,
|
memberId = member.id!!,
|
||||||
@@ -114,6 +141,56 @@ class AudioContentMainService(
|
|||||||
return GetNewContentAllResponse(totalCount, translatedContentList)
|
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)
|
@Transactional(readOnly = true)
|
||||||
@Cacheable(cacheNames = ["default"], key = "'newContentUploadCreatorList:' + #memberId + ':' + #isAdult")
|
@Cacheable(cacheNames = ["default"], key = "'newContentUploadCreatorList:' + #memberId + ':' + #isAdult")
|
||||||
fun getNewContentUploadCreatorList(memberId: Long, isAdult: Boolean): List<ContentCreatorResponse> {
|
fun getNewContentUploadCreatorList(memberId: Long, isAdult: Boolean): List<ContentCreatorResponse> {
|
||||||
|
|||||||
Reference in New Issue
Block a user