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.CurationSection
|
||||||
import kr.co.vividnext.sodalive.chat.character.dto.OtherCharacter
|
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.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.ChatCharacterBannerService
|
||||||
import kr.co.vividnext.sodalive.chat.character.service.ChatCharacterService
|
import kr.co.vividnext.sodalive.chat.character.service.ChatCharacterService
|
||||||
import kr.co.vividnext.sodalive.chat.character.translate.AiCharacterTranslation
|
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.RequestMapping
|
||||||
import org.springframework.web.bind.annotation.RequestParam
|
import org.springframework.web.bind.annotation.RequestParam
|
||||||
import org.springframework.web.bind.annotation.RestController
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
import kotlin.collections.map
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/chat/character")
|
@RequestMapping("/api/chat/character")
|
||||||
@@ -51,6 +53,7 @@ class ChatCharacterController(
|
|||||||
) {
|
) {
|
||||||
@GetMapping("/main")
|
@GetMapping("/main")
|
||||||
fun getCharacterMain(
|
fun getCharacterMain(
|
||||||
|
@RequestParam(required = false) languageCode: String? = null,
|
||||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
||||||
): ApiResponse<CharacterMainResponse> = run {
|
): ApiResponse<CharacterMainResponse> = run {
|
||||||
// 배너 조회 (최대 10개)
|
// 배너 조회 (최대 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()
|
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(
|
val newCharacters = service.getRecentCharactersPage(
|
||||||
page = 0,
|
page = 0,
|
||||||
size = 50
|
size = 50
|
||||||
).content
|
).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개 조회
|
// 최근 대화한 캐릭터를 제외한 랜덤 30개 조회
|
||||||
// Controller에서는 호출만
|
// Controller에서는 호출만
|
||||||
@@ -93,6 +191,38 @@ class ChatCharacterController(
|
|||||||
val excludeIds = recentCharacters.map { it.characterId }
|
val excludeIds = recentCharacters.map { it.characterId }
|
||||||
val recommendCharacters = service.getRecommendCharacters(excludeIds, 30)
|
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()
|
val curationSections = curationQueryService.getActiveCurationsWithCharacters()
|
||||||
.map { agg ->
|
.map { agg ->
|
||||||
@@ -115,10 +245,10 @@ class ChatCharacterController(
|
|||||||
ApiResponse.ok(
|
ApiResponse.ok(
|
||||||
CharacterMainResponse(
|
CharacterMainResponse(
|
||||||
banners = banners,
|
banners = banners,
|
||||||
recentCharacters = recentCharacters,
|
recentCharacters = translatedRecentCharacters,
|
||||||
popularCharacters = popularCharacters,
|
popularCharacters = translatedPopularCharacters,
|
||||||
newCharacters = newCharacters,
|
newCharacters = translatedNewCharacters,
|
||||||
recommendCharacters = recommendCharacters,
|
recommendCharacters = translatedRecommendCharacters,
|
||||||
curationSections = curationSections
|
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개 조회
|
// 최신 댓글 1개 조회
|
||||||
val latestComment = characterCommentService.getLatestComment(imageHost, character.id!!)
|
val latestComment = characterCommentService.getLatestComment(imageHost, character.id!!)
|
||||||
|
|
||||||
@@ -311,7 +475,7 @@ class ChatCharacterController(
|
|||||||
originalTitle = character.originalTitle,
|
originalTitle = character.originalTitle,
|
||||||
originalLink = character.originalLink,
|
originalLink = character.originalLink,
|
||||||
characterType = character.characterType,
|
characterType = character.characterType,
|
||||||
others = others,
|
others = translatedOthers,
|
||||||
latestComment = latestComment,
|
latestComment = latestComment,
|
||||||
totalComments = characterCommentService.getTotalCommentCount(character.id!!),
|
totalComments = characterCommentService.getTotalCommentCount(character.id!!),
|
||||||
translated = translated
|
translated = translated
|
||||||
@@ -325,13 +489,53 @@ class ChatCharacterController(
|
|||||||
* - 예외: 2주 이내 캐릭터가 0개인 경우, 최근 등록한 캐릭터 20개만 제공
|
* - 예외: 2주 이내 캐릭터가 0개인 경우, 최근 등록한 캐릭터 20개만 제공
|
||||||
*/
|
*/
|
||||||
@GetMapping("/recent")
|
@GetMapping("/recent")
|
||||||
fun getRecentCharacters(@RequestParam("page", required = false) page: Int?) = run {
|
fun getRecentCharacters(
|
||||||
ApiResponse.ok(
|
@RequestParam(required = false) languageCode: String? = null,
|
||||||
service.getRecentCharactersPage(
|
@RequestParam("page", required = false) page: Int?
|
||||||
page = page ?: 0,
|
): ApiResponse<RecentCharactersResponse> = run {
|
||||||
size = 20
|
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")
|
@GetMapping("/recommend")
|
||||||
fun getRecommendCharacters(
|
fun getRecommendCharacters(
|
||||||
|
@RequestParam(required = false) languageCode: String? = null,
|
||||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
||||||
) = run {
|
) = run {
|
||||||
val recent = if (member == null || member.auth == null) {
|
val recent = if (member == null || member.auth == null) {
|
||||||
@@ -350,6 +555,40 @@ class ChatCharacterController(
|
|||||||
.listMyChatRooms(member, 0, 50) // 최근 기록은 최대 50개까지만 제외 대상으로 고려
|
.listMyChatRooms(member, 0, 50) // 최근 기록은 최대 50개까지만 제외 대상으로 고려
|
||||||
.map { it.characterId }
|
.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