캐릭터 챗봇 #338
| @@ -7,16 +7,16 @@ import javax.persistence.JoinColumn | |||||||
| import javax.persistence.ManyToOne | import javax.persistence.ManyToOne | ||||||
| 
 | 
 | ||||||
| @Entity | @Entity | ||||||
| class CharacterChatMessage( | class ChatMessage( | ||||||
|     val message: String, |     val message: String, | ||||||
| 
 | 
 | ||||||
|     @ManyToOne(fetch = FetchType.LAZY) |     @ManyToOne(fetch = FetchType.LAZY) | ||||||
|     @JoinColumn(name = "chat_room_id", nullable = false) |     @JoinColumn(name = "chat_room_id", nullable = false) | ||||||
|     val chatRoom: CharacterChatRoom, |     val chatRoom: ChatRoom, | ||||||
| 
 | 
 | ||||||
|     @ManyToOne(fetch = FetchType.LAZY) |     @ManyToOne(fetch = FetchType.LAZY) | ||||||
|     @JoinColumn(name = "participant_id", nullable = false) |     @JoinColumn(name = "participant_id", nullable = false) | ||||||
|     val participant: CharacterChatParticipant, |     val participant: ChatParticipant, | ||||||
| 
 | 
 | ||||||
|     val isActive: Boolean = true |     val isActive: Boolean = true | ||||||
| ) : BaseEntity() | ) : BaseEntity() | ||||||
| @@ -13,10 +13,10 @@ import javax.persistence.ManyToOne | |||||||
| import javax.persistence.OneToMany | import javax.persistence.OneToMany | ||||||
| 
 | 
 | ||||||
| @Entity | @Entity | ||||||
| class CharacterChatParticipant( | class ChatParticipant( | ||||||
|     @ManyToOne(fetch = FetchType.LAZY) |     @ManyToOne(fetch = FetchType.LAZY) | ||||||
|     @JoinColumn(name = "chat_room_id", nullable = false) |     @JoinColumn(name = "chat_room_id", nullable = false) | ||||||
|     val chatRoom: CharacterChatRoom, |     val chatRoom: ChatRoom, | ||||||
| 
 | 
 | ||||||
|     @Enumerated(EnumType.STRING) |     @Enumerated(EnumType.STRING) | ||||||
|     val participantType: ParticipantType, |     val participantType: ParticipantType, | ||||||
| @@ -32,7 +32,7 @@ class CharacterChatParticipant( | |||||||
|     var isActive: Boolean = true |     var isActive: Boolean = true | ||||||
| ) : BaseEntity() { | ) : BaseEntity() { | ||||||
|     @OneToMany(mappedBy = "participant", cascade = [CascadeType.ALL], fetch = FetchType.LAZY) |     @OneToMany(mappedBy = "participant", cascade = [CascadeType.ALL], fetch = FetchType.LAZY) | ||||||
|     val messages: MutableList<CharacterChatMessage> = mutableListOf() |     val messages: MutableList<ChatMessage> = mutableListOf() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| enum class ParticipantType { | enum class ParticipantType { | ||||||
| @@ -7,14 +7,14 @@ import javax.persistence.FetchType | |||||||
| import javax.persistence.OneToMany | import javax.persistence.OneToMany | ||||||
| 
 | 
 | ||||||
| @Entity | @Entity | ||||||
| class CharacterChatRoom( | class ChatRoom( | ||||||
|     val sessionId: String, |     val sessionId: String, | ||||||
|     val title: String, |     val title: String, | ||||||
|     val isActive: Boolean = true |     val isActive: Boolean = true | ||||||
| ) : BaseEntity() { | ) : BaseEntity() { | ||||||
|     @OneToMany(mappedBy = "chatRoom", cascade = [CascadeType.ALL], fetch = FetchType.LAZY) |     @OneToMany(mappedBy = "chatRoom", cascade = [CascadeType.ALL], fetch = FetchType.LAZY) | ||||||
|     val messages: MutableList<CharacterChatMessage> = mutableListOf() |     val messages: MutableList<ChatMessage> = mutableListOf() | ||||||
| 
 | 
 | ||||||
|     @OneToMany(mappedBy = "chatRoom", cascade = [CascadeType.ALL], fetch = FetchType.LAZY) |     @OneToMany(mappedBy = "chatRoom", cascade = [CascadeType.ALL], fetch = FetchType.LAZY) | ||||||
|     val participants: MutableList<CharacterChatParticipant> = mutableListOf() |     val participants: MutableList<ChatParticipant> = mutableListOf() | ||||||
| } | } | ||||||
| @@ -1,18 +1,18 @@ | |||||||
| package kr.co.vividnext.sodalive.chat.room.repository | package kr.co.vividnext.sodalive.chat.room.repository | ||||||
| 
 | 
 | ||||||
| import kr.co.vividnext.sodalive.chat.room.CharacterChatMessage | import kr.co.vividnext.sodalive.chat.room.ChatMessage | ||||||
| import kr.co.vividnext.sodalive.chat.room.CharacterChatRoom | import kr.co.vividnext.sodalive.chat.room.ChatRoom | ||||||
| import org.springframework.data.jpa.repository.JpaRepository | import org.springframework.data.jpa.repository.JpaRepository | ||||||
| import org.springframework.stereotype.Repository | import org.springframework.stereotype.Repository | ||||||
| 
 | 
 | ||||||
| @Repository | @Repository | ||||||
| interface CharacterChatMessageRepository : JpaRepository<CharacterChatMessage, Long> { | interface ChatMessageRepository : JpaRepository<ChatMessage, Long> { | ||||||
|     fun findTopByChatRoomAndIsActiveTrueOrderByCreatedAtDesc(chatRoom: CharacterChatRoom): CharacterChatMessage? |     fun findTopByChatRoomAndIsActiveTrueOrderByCreatedAtDesc(chatRoom: ChatRoom): ChatMessage? | ||||||
| 
 | 
 | ||||||
|     fun findTop20ByChatRoomAndIsActiveTrueOrderByIdDesc(chatRoom: CharacterChatRoom): List<CharacterChatMessage> |     fun findTop20ByChatRoomAndIsActiveTrueOrderByIdDesc(chatRoom: ChatRoom): List<ChatMessage> | ||||||
| 
 | 
 | ||||||
|     fun findTop20ByChatRoomAndIdLessThanAndIsActiveTrueOrderByIdDesc( |     fun findTop20ByChatRoomAndIdLessThanAndIsActiveTrueOrderByIdDesc( | ||||||
|         chatRoom: CharacterChatRoom, |         chatRoom: ChatRoom, | ||||||
|         id: Long |         id: Long | ||||||
|     ): List<CharacterChatMessage> |     ): List<ChatMessage> | ||||||
| } | } | ||||||
| @@ -1,36 +1,36 @@ | |||||||
| package kr.co.vividnext.sodalive.chat.room.repository | package kr.co.vividnext.sodalive.chat.room.repository | ||||||
| 
 | 
 | ||||||
| import kr.co.vividnext.sodalive.chat.room.CharacterChatParticipant | import kr.co.vividnext.sodalive.chat.room.ChatParticipant | ||||||
| import kr.co.vividnext.sodalive.chat.room.CharacterChatRoom | import kr.co.vividnext.sodalive.chat.room.ChatRoom | ||||||
| import kr.co.vividnext.sodalive.chat.room.ParticipantType | import kr.co.vividnext.sodalive.chat.room.ParticipantType | ||||||
| import kr.co.vividnext.sodalive.member.Member | import kr.co.vividnext.sodalive.member.Member | ||||||
| import org.springframework.data.jpa.repository.JpaRepository | import org.springframework.data.jpa.repository.JpaRepository | ||||||
| import org.springframework.stereotype.Repository | import org.springframework.stereotype.Repository | ||||||
| 
 | 
 | ||||||
| @Repository | @Repository | ||||||
| interface CharacterChatParticipantRepository : JpaRepository<CharacterChatParticipant, Long> { | interface ChatParticipantRepository : JpaRepository<ChatParticipant, Long> { | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 특정 채팅방에 참여 중인 멤버 참여자 찾기 |      * 특정 채팅방에 참여 중인 멤버 참여자 찾기 | ||||||
|      */ |      */ | ||||||
|     fun findByChatRoomAndMemberAndIsActiveTrue( |     fun findByChatRoomAndMemberAndIsActiveTrue( | ||||||
|         chatRoom: CharacterChatRoom, |         chatRoom: ChatRoom, | ||||||
|         member: Member |         member: Member | ||||||
|     ): CharacterChatParticipant? |     ): ChatParticipant? | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 특정 채팅방에 특정 타입(CHARACTER/USER)으로 활성 상태인 참여자 찾기 |      * 특정 채팅방에 특정 타입(CHARACTER/USER)으로 활성 상태인 참여자 찾기 | ||||||
|      */ |      */ | ||||||
|     fun findByChatRoomAndParticipantTypeAndIsActiveTrue( |     fun findByChatRoomAndParticipantTypeAndIsActiveTrue( | ||||||
|         chatRoom: CharacterChatRoom, |         chatRoom: ChatRoom, | ||||||
|         participantType: ParticipantType |         participantType: ParticipantType | ||||||
|     ): CharacterChatParticipant? |     ): ChatParticipant? | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 특정 채팅방의 활성 USER 참여자 수 |      * 특정 채팅방의 활성 USER 참여자 수 | ||||||
|      */ |      */ | ||||||
|     fun countByChatRoomAndParticipantTypeAndIsActiveTrue( |     fun countByChatRoomAndParticipantTypeAndIsActiveTrue( | ||||||
|         chatRoom: CharacterChatRoom, |         chatRoom: ChatRoom, | ||||||
|         participantType: ParticipantType |         participantType: ParticipantType | ||||||
|     ): Long |     ): Long | ||||||
| } | } | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| package kr.co.vividnext.sodalive.chat.room.repository | package kr.co.vividnext.sodalive.chat.room.repository | ||||||
| 
 | 
 | ||||||
| import kr.co.vividnext.sodalive.chat.character.ChatCharacter | import kr.co.vividnext.sodalive.chat.character.ChatCharacter | ||||||
| import kr.co.vividnext.sodalive.chat.room.CharacterChatRoom | import kr.co.vividnext.sodalive.chat.room.ChatRoom | ||||||
| import kr.co.vividnext.sodalive.chat.room.dto.ChatRoomListQueryDto | import kr.co.vividnext.sodalive.chat.room.dto.ChatRoomListQueryDto | ||||||
| import kr.co.vividnext.sodalive.member.Member | import kr.co.vividnext.sodalive.member.Member | ||||||
| import org.springframework.data.jpa.repository.JpaRepository | import org.springframework.data.jpa.repository.JpaRepository | ||||||
| @@ -10,14 +10,14 @@ import org.springframework.data.repository.query.Param | |||||||
| import org.springframework.stereotype.Repository | import org.springframework.stereotype.Repository | ||||||
| 
 | 
 | ||||||
| @Repository | @Repository | ||||||
| interface CharacterChatRoomRepository : JpaRepository<CharacterChatRoom, Long> { | interface ChatRoomRepository : JpaRepository<ChatRoom, Long> { | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 특정 멤버와 캐릭터가 참여 중인 활성화된 채팅방을 찾는 쿼리 |      * 특정 멤버와 캐릭터가 참여 중인 활성화된 채팅방을 찾는 쿼리 | ||||||
|      */ |      */ | ||||||
|     @Query( |     @Query( | ||||||
|         """ |         """ | ||||||
|         SELECT DISTINCT r FROM CharacterChatRoom r |         SELECT DISTINCT r FROM ChatRoom r | ||||||
|         JOIN r.participants p1 |         JOIN r.participants p1 | ||||||
|         JOIN r.participants p2 |         JOIN r.participants p2 | ||||||
|         WHERE p1.member = :member AND p1.isActive = true |         WHERE p1.member = :member AND p1.isActive = true | ||||||
| @@ -28,7 +28,7 @@ interface CharacterChatRoomRepository : JpaRepository<CharacterChatRoom, Long> { | |||||||
|     fun findActiveChatRoomByMemberAndCharacter( |     fun findActiveChatRoomByMemberAndCharacter( | ||||||
|         @Param("member") member: Member, |         @Param("member") member: Member, | ||||||
|         @Param("character") character: ChatCharacter |         @Param("character") character: ChatCharacter | ||||||
|     ): CharacterChatRoom? |     ): ChatRoom? | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 멤버가 참여 중인 채팅방을 최근 메시지 시간 순으로 페이징 조회 |      * 멤버가 참여 중인 채팅방을 최근 메시지 시간 순으로 페이징 조회 | ||||||
| @@ -41,7 +41,7 @@ interface CharacterChatRoomRepository : JpaRepository<CharacterChatRoom, Long> { | |||||||
|                 r.title, |                 r.title, | ||||||
|                 pc.character.imagePath |                 pc.character.imagePath | ||||||
|             ) |             ) | ||||||
|             FROM CharacterChatRoom r |             FROM ChatRoom r | ||||||
|             JOIN r.participants p |             JOIN r.participants p | ||||||
|             JOIN r.participants pc |             JOIN r.participants pc | ||||||
|             LEFT JOIN r.messages m |             LEFT JOIN r.messages m | ||||||
| @@ -2,9 +2,9 @@ package kr.co.vividnext.sodalive.chat.room.service | |||||||
|  |  | ||||||
| import com.fasterxml.jackson.databind.ObjectMapper | import com.fasterxml.jackson.databind.ObjectMapper | ||||||
| import kr.co.vividnext.sodalive.chat.character.service.ChatCharacterService | import kr.co.vividnext.sodalive.chat.character.service.ChatCharacterService | ||||||
| import kr.co.vividnext.sodalive.chat.room.CharacterChatMessage | import kr.co.vividnext.sodalive.chat.room.ChatMessage | ||||||
| import kr.co.vividnext.sodalive.chat.room.CharacterChatParticipant | import kr.co.vividnext.sodalive.chat.room.ChatParticipant | ||||||
| import kr.co.vividnext.sodalive.chat.room.CharacterChatRoom | import kr.co.vividnext.sodalive.chat.room.ChatRoom | ||||||
| import kr.co.vividnext.sodalive.chat.room.ParticipantType | import kr.co.vividnext.sodalive.chat.room.ParticipantType | ||||||
| import kr.co.vividnext.sodalive.chat.room.dto.ChatMessageItemDto | import kr.co.vividnext.sodalive.chat.room.dto.ChatMessageItemDto | ||||||
| import kr.co.vividnext.sodalive.chat.room.dto.ChatRoomListItemDto | import kr.co.vividnext.sodalive.chat.room.dto.ChatRoomListItemDto | ||||||
| @@ -14,9 +14,9 @@ import kr.co.vividnext.sodalive.chat.room.dto.ExternalChatSendResponse | |||||||
| import kr.co.vividnext.sodalive.chat.room.dto.ExternalChatSessionCreateResponse | import kr.co.vividnext.sodalive.chat.room.dto.ExternalChatSessionCreateResponse | ||||||
| import kr.co.vividnext.sodalive.chat.room.dto.ExternalChatSessionGetResponse | import kr.co.vividnext.sodalive.chat.room.dto.ExternalChatSessionGetResponse | ||||||
| import kr.co.vividnext.sodalive.chat.room.dto.SendChatMessageResponse | import kr.co.vividnext.sodalive.chat.room.dto.SendChatMessageResponse | ||||||
| import kr.co.vividnext.sodalive.chat.room.repository.CharacterChatMessageRepository | import kr.co.vividnext.sodalive.chat.room.repository.ChatMessageRepository | ||||||
| import kr.co.vividnext.sodalive.chat.room.repository.CharacterChatParticipantRepository | import kr.co.vividnext.sodalive.chat.room.repository.ChatParticipantRepository | ||||||
| import kr.co.vividnext.sodalive.chat.room.repository.CharacterChatRoomRepository | import kr.co.vividnext.sodalive.chat.room.repository.ChatRoomRepository | ||||||
| import kr.co.vividnext.sodalive.common.SodaException | import kr.co.vividnext.sodalive.common.SodaException | ||||||
| import kr.co.vividnext.sodalive.member.Member | import kr.co.vividnext.sodalive.member.Member | ||||||
| import org.slf4j.LoggerFactory | import org.slf4j.LoggerFactory | ||||||
| @@ -33,9 +33,9 @@ import java.util.UUID | |||||||
|  |  | ||||||
| @Service | @Service | ||||||
| class ChatRoomService( | class ChatRoomService( | ||||||
|     private val chatRoomRepository: CharacterChatRoomRepository, |     private val chatRoomRepository: ChatRoomRepository, | ||||||
|     private val participantRepository: CharacterChatParticipantRepository, |     private val participantRepository: ChatParticipantRepository, | ||||||
|     private val messageRepository: CharacterChatMessageRepository, |     private val messageRepository: ChatMessageRepository, | ||||||
|     private val characterService: ChatCharacterService, |     private val characterService: ChatCharacterService, | ||||||
|  |  | ||||||
|     @Value("\${weraser.api-key}") |     @Value("\${weraser.api-key}") | ||||||
| @@ -78,7 +78,7 @@ class ChatRoomService( | |||||||
|         val sessionId = callExternalApiForChatSession(userId, character.characterUUID) |         val sessionId = callExternalApiForChatSession(userId, character.characterUUID) | ||||||
|  |  | ||||||
|         // 5. 채팅방 생성 |         // 5. 채팅방 생성 | ||||||
|         val chatRoom = CharacterChatRoom( |         val chatRoom = ChatRoom( | ||||||
|             sessionId = sessionId, |             sessionId = sessionId, | ||||||
|             title = character.name, |             title = character.name, | ||||||
|             isActive = true |             isActive = true | ||||||
| @@ -86,7 +86,7 @@ class ChatRoomService( | |||||||
|         val savedChatRoom = chatRoomRepository.save(chatRoom) |         val savedChatRoom = chatRoomRepository.save(chatRoom) | ||||||
|  |  | ||||||
|         // 6. 채팅방 참여자 추가 (멤버) |         // 6. 채팅방 참여자 추가 (멤버) | ||||||
|         val memberParticipant = CharacterChatParticipant( |         val memberParticipant = ChatParticipant( | ||||||
|             chatRoom = savedChatRoom, |             chatRoom = savedChatRoom, | ||||||
|             participantType = ParticipantType.USER, |             participantType = ParticipantType.USER, | ||||||
|             member = member, |             member = member, | ||||||
| @@ -96,7 +96,7 @@ class ChatRoomService( | |||||||
|         participantRepository.save(memberParticipant) |         participantRepository.save(memberParticipant) | ||||||
|  |  | ||||||
|         // 7. 채팅방 참여자 추가 (캐릭터) |         // 7. 채팅방 참여자 추가 (캐릭터) | ||||||
|         val characterParticipant = CharacterChatParticipant( |         val characterParticipant = ChatParticipant( | ||||||
|             chatRoom = savedChatRoom, |             chatRoom = savedChatRoom, | ||||||
|             participantType = ParticipantType.CHARACTER, |             participantType = ParticipantType.CHARACTER, | ||||||
|             member = null, |             member = null, | ||||||
| @@ -186,7 +186,7 @@ class ChatRoomService( | |||||||
|     fun listMyChatRooms(member: Member): List<ChatRoomListItemDto> { |     fun listMyChatRooms(member: Member): List<ChatRoomListItemDto> { | ||||||
|         val rooms: List<ChatRoomListQueryDto> = chatRoomRepository.findMemberRoomsOrderByLastMessageDesc(member) |         val rooms: List<ChatRoomListQueryDto> = chatRoomRepository.findMemberRoomsOrderByLastMessageDesc(member) | ||||||
|         return rooms.map { q -> |         return rooms.map { q -> | ||||||
|             val room = CharacterChatRoom( |             val room = ChatRoom( | ||||||
|                 sessionId = "", |                 sessionId = "", | ||||||
|                 title = q.title, |                 title = q.title, | ||||||
|                 isActive = true |                 isActive = true | ||||||
| @@ -388,7 +388,7 @@ class ChatRoomService( | |||||||
|         val characterReply = callExternalApiForChatSendWithRetry(userId, characterUUID, message, sessionId) |         val characterReply = callExternalApiForChatSendWithRetry(userId, characterUUID, message, sessionId) | ||||||
|  |  | ||||||
|         // 6) 내 메시지 저장 |         // 6) 내 메시지 저장 | ||||||
|         val myMsgEntity = CharacterChatMessage( |         val myMsgEntity = ChatMessage( | ||||||
|             message = message, |             message = message, | ||||||
|             chatRoom = room, |             chatRoom = room, | ||||||
|             participant = myParticipant, |             participant = myParticipant, | ||||||
| @@ -397,7 +397,7 @@ class ChatRoomService( | |||||||
|         messageRepository.save(myMsgEntity) |         messageRepository.save(myMsgEntity) | ||||||
|  |  | ||||||
|         // 7) 캐릭터 메시지 저장 |         // 7) 캐릭터 메시지 저장 | ||||||
|         val characterMsgEntity = CharacterChatMessage( |         val characterMsgEntity = ChatMessage( | ||||||
|             message = characterReply, |             message = characterReply, | ||||||
|             chatRoom = room, |             chatRoom = room, | ||||||
|             participant = characterParticipant, |             participant = characterParticipant, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user