AI 캐릭터 리스트에 번역 데이터 제공 기능 추가
This commit is contained in:
@@ -11,6 +11,7 @@ import kr.co.vividnext.sodalive.chat.character.dto.CharacterPersonalityResponse
|
||||
import kr.co.vividnext.sodalive.chat.character.dto.CurationSection
|
||||
import kr.co.vividnext.sodalive.chat.character.dto.OtherCharacter
|
||||
import kr.co.vividnext.sodalive.chat.character.dto.RecentCharacter
|
||||
import kr.co.vividnext.sodalive.chat.character.dto.RecentCharactersResponse
|
||||
import kr.co.vividnext.sodalive.chat.character.service.ChatCharacterBannerService
|
||||
import kr.co.vividnext.sodalive.chat.character.service.ChatCharacterService
|
||||
import kr.co.vividnext.sodalive.chat.character.translate.AiCharacterTranslation
|
||||
@@ -33,6 +34,7 @@ import org.springframework.web.bind.annotation.PathVariable
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RequestParam
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import kotlin.collections.map
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/chat/character")
|
||||
@@ -51,6 +53,7 @@ class ChatCharacterController(
|
||||
) {
|
||||
@GetMapping("/main")
|
||||
fun getCharacterMain(
|
||||
@RequestParam(required = false) languageCode: String? = null,
|
||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
||||
): ApiResponse<CharacterMainResponse> = run {
|
||||
// 배너 조회 (최대 10개)
|
||||
@@ -77,15 +80,110 @@ class ChatCharacterController(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 최근 대화한 캐릭터 이름 번역 데이터 조회
|
||||
*
|
||||
* languageCode != null
|
||||
* aiCharacterTranslationRepository 이용해 번역 콘텐츠를 조회한다. - characterId, locale
|
||||
*
|
||||
* 한 번에 조회하고 characterId 매핑하여 recentCharacters 캐릭터 이름을 번역 데이터로 변경한다
|
||||
*/
|
||||
val translatedRecentCharacters = if (!languageCode.isNullOrBlank()) {
|
||||
val characterIds = recentCharacters.map { it.characterId }
|
||||
|
||||
if (characterIds.isNotEmpty()) {
|
||||
val translations = aiCharacterTranslationRepository
|
||||
.findByCharacterIdInAndLocale(characterIds = characterIds, locale = languageCode)
|
||||
.associateBy { it.characterId }
|
||||
|
||||
recentCharacters.map { character ->
|
||||
val translatedName = translations[character.characterId]?.renderedPayload?.name
|
||||
if (translatedName.isNullOrBlank()) {
|
||||
character
|
||||
} else {
|
||||
character.copy(name = translatedName)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
recentCharacters
|
||||
}
|
||||
} else {
|
||||
recentCharacters
|
||||
}
|
||||
|
||||
// 인기 캐릭터 조회
|
||||
val popularCharacters = service.getPopularCharacters()
|
||||
|
||||
/**
|
||||
* popularCharacters 캐릭터 이름과 description 번역 데이터 조회
|
||||
*
|
||||
* languageCode != null
|
||||
* aiCharacterTranslationRepository 이용해 번역 콘텐츠를 조회한다. - characterId, locale
|
||||
*
|
||||
* 한 번에 조회하고 characterId 매핑하여 popularCharacters의 캐릭터 이름과 description을 번역 데이터로 변경한다
|
||||
*/
|
||||
val translatedPopularCharacters = if (!languageCode.isNullOrBlank()) {
|
||||
val characterIds = popularCharacters.map { it.characterId }
|
||||
|
||||
if (characterIds.isNotEmpty()) {
|
||||
val translations = aiCharacterTranslationRepository
|
||||
.findByCharacterIdInAndLocale(characterIds = characterIds, locale = languageCode)
|
||||
.associateBy { it.characterId }
|
||||
|
||||
popularCharacters.map { character ->
|
||||
val translatedName = translations[character.characterId]?.renderedPayload?.name
|
||||
val translatedDesc = translations[character.characterId]?.renderedPayload?.description
|
||||
if (translatedName.isNullOrBlank() || translatedDesc.isNullOrBlank()) {
|
||||
character
|
||||
} else {
|
||||
character.copy(name = translatedName, description = translatedDesc)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
popularCharacters
|
||||
}
|
||||
} else {
|
||||
popularCharacters
|
||||
}
|
||||
|
||||
// 최근 등록된 캐릭터 리스트 조회
|
||||
val newCharacters = service.getRecentCharactersPage(
|
||||
page = 0,
|
||||
size = 50
|
||||
).content
|
||||
|
||||
/**
|
||||
* 최근 등록된 캐릭터 이름 번역 데이터 조회
|
||||
*
|
||||
* languageCode != null
|
||||
* aiCharacterTranslationRepository 이용해 번역 콘텐츠를 조회한다. - characterId, locale
|
||||
*
|
||||
* 한 번에 조회하고 characterId 매핑하여 newCharacters 캐릭터 이름과 description을 번역 데이터로 변경한다
|
||||
*/
|
||||
val translatedNewCharacters = if (!languageCode.isNullOrBlank()) {
|
||||
val characterIds = newCharacters.map { it.characterId }
|
||||
|
||||
if (characterIds.isNotEmpty()) {
|
||||
val translations = aiCharacterTranslationRepository
|
||||
.findByCharacterIdInAndLocale(characterIds = characterIds, locale = languageCode)
|
||||
.associateBy { it.characterId }
|
||||
|
||||
newCharacters.map { character ->
|
||||
val translatedName = translations[character.characterId]?.renderedPayload?.name
|
||||
val translatedDesc = translations[character.characterId]?.renderedPayload?.description
|
||||
if (translatedName.isNullOrBlank() || translatedDesc.isNullOrBlank()) {
|
||||
character
|
||||
} else {
|
||||
character.copy(name = translatedName, description = translatedDesc)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
newCharacters
|
||||
}
|
||||
} else {
|
||||
newCharacters
|
||||
}
|
||||
|
||||
// 추천 캐릭터 조회
|
||||
// 최근 대화한 캐릭터를 제외한 랜덤 30개 조회
|
||||
// Controller에서는 호출만
|
||||
@@ -93,6 +191,38 @@ class ChatCharacterController(
|
||||
val excludeIds = recentCharacters.map { it.characterId }
|
||||
val recommendCharacters = service.getRecommendCharacters(excludeIds, 30)
|
||||
|
||||
/**
|
||||
* 추천 캐릭터 이름 번역 데이터 조회
|
||||
*
|
||||
* languageCode != null
|
||||
* aiCharacterTranslationRepository 이용해 번역 콘텐츠를 조회한다. - characterId, locale
|
||||
*
|
||||
* 한 번에 조회하고 characterId 매핑하여 recommendCharacters 캐릭터 이름과 description을 번역 데이터로 변경한다
|
||||
*/
|
||||
val translatedRecommendCharacters = if (!languageCode.isNullOrBlank()) {
|
||||
val characterIds = recommendCharacters.map { it.characterId }
|
||||
|
||||
if (characterIds.isNotEmpty()) {
|
||||
val translations = aiCharacterTranslationRepository
|
||||
.findByCharacterIdInAndLocale(characterIds = characterIds, locale = languageCode)
|
||||
.associateBy { it.characterId }
|
||||
|
||||
recommendCharacters.map { character ->
|
||||
val translatedName = translations[character.characterId]?.renderedPayload?.name
|
||||
val translatedDesc = translations[character.characterId]?.renderedPayload?.description
|
||||
if (translatedName.isNullOrBlank() || translatedDesc.isNullOrBlank()) {
|
||||
character
|
||||
} else {
|
||||
character.copy(name = translatedName, description = translatedDesc)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
recommendCharacters
|
||||
}
|
||||
} else {
|
||||
recommendCharacters
|
||||
}
|
||||
|
||||
// 큐레이션 섹션 (활성화된 큐레이션 + 캐릭터)
|
||||
val curationSections = curationQueryService.getActiveCurationsWithCharacters()
|
||||
.map { agg ->
|
||||
@@ -115,10 +245,10 @@ class ChatCharacterController(
|
||||
ApiResponse.ok(
|
||||
CharacterMainResponse(
|
||||
banners = banners,
|
||||
recentCharacters = recentCharacters,
|
||||
popularCharacters = popularCharacters,
|
||||
newCharacters = newCharacters,
|
||||
recommendCharacters = recommendCharacters,
|
||||
recentCharacters = translatedRecentCharacters,
|
||||
popularCharacters = translatedPopularCharacters,
|
||||
newCharacters = translatedNewCharacters,
|
||||
recommendCharacters = translatedRecommendCharacters,
|
||||
curationSections = curationSections
|
||||
)
|
||||
)
|
||||
@@ -291,6 +421,40 @@ class ChatCharacterController(
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 다른 캐릭터 이름, 태그 번역 데이터 조회
|
||||
*
|
||||
* languageCode != null
|
||||
* aiCharacterTranslationRepository 이용해 번역 콘텐츠를 조회한다. - characterId, locale
|
||||
*
|
||||
* 한 번에 조회하고 characterId 매핑하여 others 캐릭터 이름과 tags 번역 데이터로 변경한다
|
||||
*/
|
||||
val translatedOthers = if (!languageCode.isNullOrBlank()) {
|
||||
val characterIds = others.map { it.characterId }
|
||||
|
||||
if (characterIds.isNotEmpty()) {
|
||||
val translations = aiCharacterTranslationRepository
|
||||
.findByCharacterIdInAndLocale(characterIds = characterIds, locale = languageCode)
|
||||
.associateBy { it.characterId }
|
||||
|
||||
others.map { other ->
|
||||
val payload = translations[other.characterId]?.renderedPayload
|
||||
val translatedName = payload?.name
|
||||
val translatedTags = payload?.tags
|
||||
|
||||
if (translatedName.isNullOrBlank() || translatedTags.isNullOrBlank()) {
|
||||
other
|
||||
} else {
|
||||
other.copy(name = translatedName, tags = translatedTags)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
others
|
||||
}
|
||||
} else {
|
||||
others
|
||||
}
|
||||
|
||||
// 최신 댓글 1개 조회
|
||||
val latestComment = characterCommentService.getLatestComment(imageHost, character.id!!)
|
||||
|
||||
@@ -311,7 +475,7 @@ class ChatCharacterController(
|
||||
originalTitle = character.originalTitle,
|
||||
originalLink = character.originalLink,
|
||||
characterType = character.characterType,
|
||||
others = others,
|
||||
others = translatedOthers,
|
||||
latestComment = latestComment,
|
||||
totalComments = characterCommentService.getTotalCommentCount(character.id!!),
|
||||
translated = translated
|
||||
@@ -325,13 +489,53 @@ class ChatCharacterController(
|
||||
* - 예외: 2주 이내 캐릭터가 0개인 경우, 최근 등록한 캐릭터 20개만 제공
|
||||
*/
|
||||
@GetMapping("/recent")
|
||||
fun getRecentCharacters(@RequestParam("page", required = false) page: Int?) = run {
|
||||
ApiResponse.ok(
|
||||
service.getRecentCharactersPage(
|
||||
page = page ?: 0,
|
||||
size = 20
|
||||
)
|
||||
fun getRecentCharacters(
|
||||
@RequestParam(required = false) languageCode: String? = null,
|
||||
@RequestParam("page", required = false) page: Int?
|
||||
): ApiResponse<RecentCharactersResponse> = run {
|
||||
val characterPage = service.getRecentCharactersPage(
|
||||
page = page ?: 0,
|
||||
size = 20
|
||||
)
|
||||
|
||||
/**
|
||||
* 최근 등록된 캐릭터 이름 번역 데이터 조회
|
||||
*
|
||||
* languageCode != null
|
||||
* aiCharacterTranslationRepository 이용해 번역 콘텐츠를 조회한다. - characterId, locale
|
||||
*
|
||||
* 한 번에 조회하고 characterId 매핑하여 characterList 캐릭터 이름과 description을 번역 데이터로 변경한다
|
||||
*/
|
||||
val translatedContent = if (!languageCode.isNullOrBlank()) {
|
||||
val characterIds = characterPage.content.map { it.characterId }
|
||||
|
||||
if (characterIds.isNotEmpty()) {
|
||||
val translations = aiCharacterTranslationRepository
|
||||
.findByCharacterIdInAndLocale(characterIds = characterIds, locale = languageCode)
|
||||
.associateBy { it.characterId }
|
||||
|
||||
characterPage.content.map { character ->
|
||||
val translatedName = translations[character.characterId]?.renderedPayload?.name
|
||||
val translatedDesc = translations[character.characterId]?.renderedPayload?.description
|
||||
if (translatedName.isNullOrBlank() || translatedDesc.isNullOrBlank()) {
|
||||
character
|
||||
} else {
|
||||
character.copy(name = translatedName, description = translatedDesc)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
characterPage.content
|
||||
}
|
||||
} else {
|
||||
characterPage.content
|
||||
}
|
||||
|
||||
val translatedCharacterPage = RecentCharactersResponse(
|
||||
totalCount = characterPage.totalCount,
|
||||
content = translatedContent
|
||||
)
|
||||
|
||||
ApiResponse.ok(translatedCharacterPage)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -341,6 +545,7 @@ class ChatCharacterController(
|
||||
*/
|
||||
@GetMapping("/recommend")
|
||||
fun getRecommendCharacters(
|
||||
@RequestParam(required = false) languageCode: String? = null,
|
||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
||||
) = run {
|
||||
val recent = if (member == null || member.auth == null) {
|
||||
@@ -350,6 +555,40 @@ class ChatCharacterController(
|
||||
.listMyChatRooms(member, 0, 50) // 최근 기록은 최대 50개까지만 제외 대상으로 고려
|
||||
.map { it.characterId }
|
||||
}
|
||||
ApiResponse.ok(service.getRecommendCharacters(recent, 20))
|
||||
val characterList = service.getRecommendCharacters(recent, 20)
|
||||
|
||||
/**
|
||||
* 추천 캐릭터 이름 번역 데이터 조회
|
||||
*
|
||||
* languageCode != null
|
||||
* aiCharacterTranslationRepository 이용해 번역 콘텐츠를 조회한다. - characterId, locale
|
||||
*
|
||||
* 한 번에 조회하고 characterId 매핑하여 characterList 캐릭터 이름과 description을 번역 데이터로 변경한다
|
||||
*/
|
||||
val translatedCharacterList = if (!languageCode.isNullOrBlank()) {
|
||||
val characterIds = characterList.map { it.characterId }
|
||||
|
||||
if (characterIds.isNotEmpty()) {
|
||||
val translations = aiCharacterTranslationRepository
|
||||
.findByCharacterIdInAndLocale(characterIds = characterIds, locale = languageCode)
|
||||
.associateBy { it.characterId }
|
||||
|
||||
characterList.map { character ->
|
||||
val translatedName = translations[character.characterId]?.renderedPayload?.name
|
||||
val translatedDesc = translations[character.characterId]?.renderedPayload?.description
|
||||
if (translatedName.isNullOrBlank() || translatedDesc.isNullOrBlank()) {
|
||||
character
|
||||
} else {
|
||||
character.copy(name = translatedName, description = translatedDesc)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
characterList
|
||||
}
|
||||
} else {
|
||||
characterList
|
||||
}
|
||||
|
||||
ApiResponse.ok(translatedCharacterList)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user