캐릭터 챗봇 #338
| @@ -45,8 +45,8 @@ class ChatCharacterController( | |||||||
|                 ) |                 ) | ||||||
|             } |             } | ||||||
|  |  | ||||||
|         // 최근 대화한 캐릭터 조회 (현재는 빈 리스트) |         // 최근 대화한 캐릭터 조회 (회원별 최근 순으로 최대 10개) | ||||||
|         val recentCharacters = service.getRecentCharacters() |         val recentCharacters = service.getRecentCharacters(member, 10) | ||||||
|             .map { |             .map { | ||||||
|                 RecentCharacter( |                 RecentCharacter( | ||||||
|                     characterId = it.id!!, |                     characterId = it.id!!, | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| package kr.co.vividnext.sodalive.chat.character.repository | package kr.co.vividnext.sodalive.chat.character.repository | ||||||
|  |  | ||||||
| import kr.co.vividnext.sodalive.chat.character.ChatCharacter | import kr.co.vividnext.sodalive.chat.character.ChatCharacter | ||||||
|  | import kr.co.vividnext.sodalive.member.Member | ||||||
| import org.springframework.data.domain.Page | import org.springframework.data.domain.Page | ||||||
| import org.springframework.data.domain.Pageable | import org.springframework.data.domain.Pageable | ||||||
| import org.springframework.data.jpa.repository.JpaRepository | import org.springframework.data.jpa.repository.JpaRepository | ||||||
| @@ -40,4 +41,29 @@ interface ChatCharacterRepository : JpaRepository<ChatCharacter, Long> { | |||||||
|         @Param("searchTerm") searchTerm: String, |         @Param("searchTerm") searchTerm: String, | ||||||
|         pageable: Pageable |         pageable: Pageable | ||||||
|     ): Page<ChatCharacter> |     ): Page<ChatCharacter> | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 멤버가 최근에 대화한 캐릭터 목록을 반환 (최신 메시지 시간 기준 내림차순) | ||||||
|  |      */ | ||||||
|  |     @Query( | ||||||
|  |         value = """ | ||||||
|  |             SELECT c FROM ChatRoom r | ||||||
|  |             JOIN r.participants pu | ||||||
|  |             JOIN r.participants pc | ||||||
|  |             JOIN pc.character c | ||||||
|  |             LEFT JOIN r.messages m | ||||||
|  |             WHERE pu.member = :member | ||||||
|  |               AND pu.participantType = kr.co.vividnext.sodalive.chat.room.ParticipantType.USER | ||||||
|  |               AND pu.isActive = true | ||||||
|  |               AND pc.participantType = kr.co.vividnext.sodalive.chat.room.ParticipantType.CHARACTER | ||||||
|  |               AND pc.isActive = true | ||||||
|  |               AND r.isActive = true | ||||||
|  |             GROUP BY c.id | ||||||
|  |             ORDER BY COALESCE(MAX(m.createdAt), r.createdAt) DESC | ||||||
|  |         """ | ||||||
|  |     ) | ||||||
|  |     fun findRecentCharactersByMember( | ||||||
|  |         @Param("member") member: Member, | ||||||
|  |         pageable: Pageable | ||||||
|  |     ): List<ChatCharacter> | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterHobbyRepo | |||||||
| import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterRepository | import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterRepository | ||||||
| import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterTagRepository | import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterTagRepository | ||||||
| import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterValueRepository | import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterValueRepository | ||||||
|  | import kr.co.vividnext.sodalive.member.Member | ||||||
| import org.springframework.data.domain.PageRequest | import org.springframework.data.domain.PageRequest | ||||||
| import org.springframework.stereotype.Service | import org.springframework.stereotype.Service | ||||||
| import org.springframework.transaction.annotation.Transactional | import org.springframework.transaction.annotation.Transactional | ||||||
| @@ -26,12 +27,11 @@ class ChatCharacterService( | |||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 최근에 대화한 캐릭터 목록 조회 |      * 최근에 대화한 캐릭터 목록 조회 | ||||||
|      * 현재는 채팅방 구현 전이므로 빈 리스트 반환 |  | ||||||
|      */ |      */ | ||||||
|     @Transactional(readOnly = true) |     @Transactional(readOnly = true) | ||||||
|     fun getRecentCharacters(): List<ChatCharacter> { |     fun getRecentCharacters(member: Member?, limit: Int = 10): List<ChatCharacter> { | ||||||
|         // 채팅방 구현 전이므로 빈 리스트 반환 |         if (member == null) return emptyList() | ||||||
|         return emptyList() |         return chatCharacterRepository.findRecentCharactersByMember(member, PageRequest.of(0, limit)) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|   | |||||||
| @@ -94,7 +94,7 @@ class SecurityConfig( | |||||||
|             .antMatchers("/ad-tracking/app-launch").permitAll() |             .antMatchers("/ad-tracking/app-launch").permitAll() | ||||||
|             .antMatchers(HttpMethod.GET, "/notice/latest").permitAll() |             .antMatchers(HttpMethod.GET, "/notice/latest").permitAll() | ||||||
|             .antMatchers(HttpMethod.GET, "/api/chat/character/main").permitAll() |             .antMatchers(HttpMethod.GET, "/api/chat/character/main").permitAll() | ||||||
|             .antMatchers(HttpMethod.GET, "/api/chat/list").permitAll() |             .antMatchers(HttpMethod.GET, "/api/chat/room/list").permitAll() | ||||||
|             .anyRequest().authenticated() |             .anyRequest().authenticated() | ||||||
|             .and() |             .and() | ||||||
|             .build() |             .build() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user