Skip to content

Commit ba2e79c

Browse files
committed
[FEAT] 챗봇 /chat 채팅방 조회 API 구현
1 parent 50fc985 commit ba2e79c

6 files changed

Lines changed: 137 additions & 0 deletions

File tree

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package fitfit.domain.chat.controller;
2+
3+
import fitfit.domain.chat.dto.ChatResponseDTO;
4+
import fitfit.domain.chat.service.ChatQueryService;
5+
import fitfit.global.apiPayload.ApiResponse;
6+
import io.swagger.v3.oas.annotations.Operation;
7+
import io.swagger.v3.oas.annotations.Parameter;
8+
import io.swagger.v3.oas.annotations.Parameters;
9+
import io.swagger.v3.oas.annotations.media.Content;
10+
import io.swagger.v3.oas.annotations.media.Schema;
11+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
12+
import io.swagger.v3.oas.annotations.tags.Tag;
13+
import lombok.RequiredArgsConstructor;
14+
import org.springframework.web.bind.annotation.*;
15+
16+
@RestController
17+
@RequestMapping("/api/chat")
18+
@RequiredArgsConstructor
19+
@Tag(name = "Chat", description = "챗봇 관련 API")
20+
public class ChatRestController {
21+
22+
private final ChatQueryService chatQueryService;
23+
24+
@GetMapping("")
25+
@Operation(summary = "챗봇 대화 내용 조회 API", description = "챗봇과 사용자의 대화 내용을 조회하는 API입니다.")
26+
@Parameters({
27+
@Parameter(name = "Authorization", description = "Bearer 액세스 토큰", required = true, in = io.swagger.v3.oas.annotations.enums.ParameterIn.HEADER)
28+
})
29+
@ApiResponses({
30+
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "OK, 성공"),
31+
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "인증이 필요합니다.", content = @Content(schema = @Schema(implementation = ApiResponse.class))),
32+
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "존재하지 않는 회원입니다.", content = @Content(schema = @Schema(implementation = ApiResponse.class)))
33+
})
34+
public ApiResponse<ChatResponseDTO.ChatHistoryDTO> getChatHistory(@RequestHeader("Authorization") String authorization) {
35+
return ApiResponse.onSuccess(chatQueryService.getChatHistory(authorization));
36+
}
37+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package fitfit.domain.chat.converter;
2+
3+
import fitfit.domain.chat.dto.ChatResponseDTO;
4+
import fitfit.domain.chat.entity.BotChat;
5+
6+
import java.util.List;
7+
import java.util.stream.Collectors;
8+
9+
public class ChatConverter {
10+
11+
public static ChatResponseDTO.ChatMessageDTO toChatMessageDTO(BotChat chat) {
12+
return ChatResponseDTO.ChatMessageDTO.builder()
13+
.sender(chat.getIsMember() ? "user" : "bot")
14+
.content(chat.getContent())
15+
.createdAt(chat.getCreatedAt())
16+
.build();
17+
}
18+
19+
public static ChatResponseDTO.ChatHistoryDTO toChatHistoryDTO(List<BotChat> chats) {
20+
List<ChatResponseDTO.ChatMessageDTO> messages = chats.stream()
21+
.map(ChatConverter::toChatMessageDTO)
22+
.collect(Collectors.toList());
23+
return ChatResponseDTO.ChatHistoryDTO.builder()
24+
.messages(messages)
25+
.build();
26+
}
27+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package fitfit.domain.chat.dto;
2+
3+
import lombok.Builder;
4+
import lombok.Getter;
5+
6+
import java.time.LocalDateTime;
7+
import java.util.List;
8+
9+
public class ChatResponseDTO {
10+
11+
@Getter
12+
@Builder
13+
public static class ChatHistoryDTO {
14+
private List<ChatMessageDTO> messages;
15+
}
16+
17+
@Getter
18+
@Builder
19+
public static class ChatMessageDTO {
20+
private String sender; // "user" or "bot"
21+
private String content;
22+
private LocalDateTime createdAt;
23+
}
24+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package fitfit.domain.chat.repository;
2+
3+
import fitfit.domain.chat.entity.BotChat;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
import java.util.List;
6+
7+
public interface BotChatRepository extends JpaRepository<BotChat, Long> {
8+
List<BotChat> findAllByMemberIdOrderByCreatedAtAsc(Long memberId);
9+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package fitfit.domain.chat.service;
2+
3+
import fitfit.domain.chat.dto.ChatResponseDTO;
4+
5+
public interface ChatQueryService {
6+
ChatResponseDTO.ChatHistoryDTO getChatHistory(String authorization);
7+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package fitfit.domain.chat.service;
2+
3+
import fitfit.domain.chat.converter.ChatConverter;
4+
import fitfit.domain.chat.dto.ChatResponseDTO;
5+
import fitfit.domain.chat.entity.BotChat;
6+
import fitfit.domain.chat.repository.BotChatRepository;
7+
import fitfit.domain.member.repository.MemberRepository;
8+
import fitfit.domain.token.provider.JwtProvider;
9+
import fitfit.global.apiPayload.code.status.ErrorStatus;
10+
import fitfit.global.apiPayload.exception.handler.MemberHandler;
11+
import lombok.RequiredArgsConstructor;
12+
import org.springframework.stereotype.Service;
13+
import org.springframework.transaction.annotation.Transactional;
14+
15+
import java.util.List;
16+
17+
@Service
18+
@RequiredArgsConstructor
19+
@Transactional(readOnly = true)
20+
public class ChatQueryServiceImpl implements ChatQueryService {
21+
22+
private final BotChatRepository botChatRepository;
23+
private final MemberRepository memberRepository;
24+
private final JwtProvider jwtProvider;
25+
26+
@Override
27+
public ChatResponseDTO.ChatHistoryDTO getChatHistory(String authorization) {
28+
Long memberId = jwtProvider.getMemberIdAndValidateToken(authorization);
29+
memberRepository.findById(memberId).orElseThrow(() -> new MemberHandler(ErrorStatus.MEMBER_NOT_FOUND));
30+
List<BotChat> chats = botChatRepository.findAllByMemberIdOrderByCreatedAtAsc(memberId);
31+
return ChatConverter.toChatHistoryDTO(chats);
32+
}
33+
}

0 commit comments

Comments
 (0)