feat(admin): 관리자 페이지 캐릭터 상세 API 구현
This commit is contained in:
parent
6340ed27cf
commit
2335050834
|
@ -21,6 +21,7 @@ import org.springframework.retry.annotation.Backoff
|
||||||
import org.springframework.retry.annotation.Retryable
|
import org.springframework.retry.annotation.Retryable
|
||||||
import org.springframework.security.access.prepost.PreAuthorize
|
import org.springframework.security.access.prepost.PreAuthorize
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable
|
||||||
import org.springframework.web.bind.annotation.PostMapping
|
import org.springframework.web.bind.annotation.PostMapping
|
||||||
import org.springframework.web.bind.annotation.PutMapping
|
import org.springframework.web.bind.annotation.PutMapping
|
||||||
import org.springframework.web.bind.annotation.RequestMapping
|
import org.springframework.web.bind.annotation.RequestMapping
|
||||||
|
@ -68,6 +69,21 @@ class AdminChatCharacterController(
|
||||||
ApiResponse.ok(response)
|
ApiResponse.ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 캐릭터 상세 정보 조회 API
|
||||||
|
*
|
||||||
|
* @param characterId 캐릭터 ID
|
||||||
|
* @return 캐릭터 상세 정보
|
||||||
|
*/
|
||||||
|
@GetMapping("/{characterId}")
|
||||||
|
fun getCharacterDetail(
|
||||||
|
@PathVariable characterId: Long
|
||||||
|
) = run {
|
||||||
|
val response = adminService.getChatCharacterDetail(characterId, imageHost)
|
||||||
|
|
||||||
|
ApiResponse.ok(response)
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/register")
|
@PostMapping("/register")
|
||||||
@Retryable(
|
@Retryable(
|
||||||
value = [Exception::class],
|
value = [Exception::class],
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.chat.character.dto
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.chat.character.ChatCharacter
|
||||||
|
|
||||||
|
data class ChatCharacterDetailResponse(
|
||||||
|
val id: Long,
|
||||||
|
val characterUUID: String,
|
||||||
|
val name: String,
|
||||||
|
val imageUrl: String?,
|
||||||
|
val description: String,
|
||||||
|
val systemPrompt: String,
|
||||||
|
val age: Int?,
|
||||||
|
val gender: String?,
|
||||||
|
val mbti: String?,
|
||||||
|
val speechPattern: String?,
|
||||||
|
val speechStyle: String?,
|
||||||
|
val appearance: String?,
|
||||||
|
val isActive: Boolean,
|
||||||
|
val tags: List<String>,
|
||||||
|
val hobbies: List<String>,
|
||||||
|
val values: List<String>,
|
||||||
|
val goals: List<String>,
|
||||||
|
val relationships: List<String>,
|
||||||
|
val personalities: List<PersonalityResponse>,
|
||||||
|
val backgrounds: List<BackgroundResponse>,
|
||||||
|
val memories: List<MemoryResponse>
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun from(chatCharacter: ChatCharacter, imageHost: String = ""): ChatCharacterDetailResponse {
|
||||||
|
val fullImagePath = if (chatCharacter.imagePath != null && imageHost.isNotEmpty()) {
|
||||||
|
"$imageHost/${chatCharacter.imagePath}"
|
||||||
|
} else {
|
||||||
|
chatCharacter.imagePath
|
||||||
|
}
|
||||||
|
|
||||||
|
return ChatCharacterDetailResponse(
|
||||||
|
id = chatCharacter.id!!,
|
||||||
|
characterUUID = chatCharacter.characterUUID,
|
||||||
|
name = chatCharacter.name,
|
||||||
|
imageUrl = fullImagePath,
|
||||||
|
description = chatCharacter.description,
|
||||||
|
systemPrompt = chatCharacter.systemPrompt,
|
||||||
|
age = chatCharacter.age,
|
||||||
|
gender = chatCharacter.gender,
|
||||||
|
mbti = chatCharacter.mbti,
|
||||||
|
speechPattern = chatCharacter.speechPattern,
|
||||||
|
speechStyle = chatCharacter.speechStyle,
|
||||||
|
appearance = chatCharacter.appearance,
|
||||||
|
isActive = chatCharacter.isActive,
|
||||||
|
tags = chatCharacter.tagMappings.map { it.tag.tag },
|
||||||
|
hobbies = chatCharacter.hobbyMappings.map { it.hobby.hobby },
|
||||||
|
values = chatCharacter.valueMappings.map { it.value.value },
|
||||||
|
goals = chatCharacter.goalMappings.map { it.goal.goal },
|
||||||
|
relationships = chatCharacter.relationships.map { it.relationShip },
|
||||||
|
personalities = chatCharacter.personalities.map {
|
||||||
|
PersonalityResponse(it.trait, it.description)
|
||||||
|
},
|
||||||
|
backgrounds = chatCharacter.backgrounds.map {
|
||||||
|
BackgroundResponse(it.topic, it.description)
|
||||||
|
},
|
||||||
|
memories = chatCharacter.memories.map {
|
||||||
|
MemoryResponse(it.title, it.content, it.emotion)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class PersonalityResponse(
|
||||||
|
val trait: String,
|
||||||
|
val description: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class BackgroundResponse(
|
||||||
|
val topic: String,
|
||||||
|
val description: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class MemoryResponse(
|
||||||
|
val title: String,
|
||||||
|
val content: String,
|
||||||
|
val emotion: String
|
||||||
|
)
|
|
@ -1,8 +1,10 @@
|
||||||
package kr.co.vividnext.sodalive.admin.chat.character.service
|
package kr.co.vividnext.sodalive.admin.chat.character.service
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.admin.chat.character.dto.ChatCharacterDetailResponse
|
||||||
import kr.co.vividnext.sodalive.admin.chat.character.dto.ChatCharacterListPageResponse
|
import kr.co.vividnext.sodalive.admin.chat.character.dto.ChatCharacterListPageResponse
|
||||||
import kr.co.vividnext.sodalive.admin.chat.character.dto.ChatCharacterListResponse
|
import kr.co.vividnext.sodalive.admin.chat.character.dto.ChatCharacterListResponse
|
||||||
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterRepository
|
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterRepository
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
import org.springframework.data.domain.PageRequest
|
import org.springframework.data.domain.PageRequest
|
||||||
import org.springframework.data.domain.Pageable
|
import org.springframework.data.domain.Pageable
|
||||||
import org.springframework.data.domain.Sort
|
import org.springframework.data.domain.Sort
|
||||||
|
@ -43,4 +45,20 @@ class AdminChatCharacterService(
|
||||||
fun createDefaultPageRequest(page: Int = 0, size: Int = 20): PageRequest {
|
fun createDefaultPageRequest(page: Int = 0, size: Int = 20): PageRequest {
|
||||||
return PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt"))
|
return PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 캐릭터 상세 정보 조회
|
||||||
|
*
|
||||||
|
* @param characterId 캐릭터 ID
|
||||||
|
* @param imageHost 이미지 호스트 URL
|
||||||
|
* @return 캐릭터 상세 정보
|
||||||
|
* @throws SodaException 캐릭터를 찾을 수 없는 경우
|
||||||
|
*/
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
fun getChatCharacterDetail(characterId: Long, imageHost: String = ""): ChatCharacterDetailResponse {
|
||||||
|
val chatCharacter = chatCharacterRepository.findById(characterId)
|
||||||
|
.orElseThrow { SodaException("해당 ID의 캐릭터를 찾을 수 없습니다: $characterId") }
|
||||||
|
|
||||||
|
return ChatCharacterDetailResponse.from(chatCharacter, imageHost)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue