diff --git a/src/main/java/com/helpmeCookies/chat/controller/ChatMessageController.java b/src/main/java/com/helpmeCookies/chat/controller/ChatMessageController.java index 30b9643..52b4d93 100644 --- a/src/main/java/com/helpmeCookies/chat/controller/ChatMessageController.java +++ b/src/main/java/com/helpmeCookies/chat/controller/ChatMessageController.java @@ -1,19 +1,21 @@ package com.helpmeCookies.chat.controller; - -import com.helpmeCookies.chat.dto.ChatRoomInfo; import com.helpmeCookies.chat.entity.ChatMessage; import com.helpmeCookies.chat.entity.ChatRoom; import com.helpmeCookies.chat.service.ChatMessageService; import com.helpmeCookies.chat.service.ChatRoomService; import com.helpmeCookies.chat.util.ImageStorageUtil; +import com.helpmeCookies.global.ApiResponse.ApiResponse; +import com.helpmeCookies.global.ApiResponse.SuccessCode; import com.helpmeCookies.global.exception.chat.ChatRoomIdNotFoundException; -import com.helpmeCookies.global.exception.user.UserNotFoundException; -import com.helpmeCookies.user.entity.User; import com.helpmeCookies.user.service.UserService; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.io.IOException; import java.util.List; @RestController @@ -25,33 +27,35 @@ public class ChatMessageController { private final UserService userService; private final ImageStorageUtil imageStorageUtil; + @GetMapping("/messages") + public ResponseEntity>> getAllMessages() { + List messages = chatMessageService.getAllMessages(); + return ResponseEntity.ok(ApiResponse.success(SuccessCode.OK, messages)); + } + @GetMapping("/rooms/{chatRoomId}/messages") - public List getMessagesByChatRoom(@PathVariable Long chatRoomId) { + public ResponseEntity>> getMessagesByChatRoom(@PathVariable Long chatRoomId) { ChatRoom chatRoom = chatRoomService.findById(chatRoomId) .orElseThrow(() -> new ChatRoomIdNotFoundException(chatRoomId)); - return chatMessageService.getMessagesByChatRoom(chatRoom); + List messages = chatMessageService.getMessagesByChatRoom(chatRoom); + return ResponseEntity.ok(ApiResponse.success(SuccessCode.OK, messages)); } - @GetMapping("/rooms/user/{userId}") - public List getChatRoomIdsByUser(@PathVariable Long userId) throws UserNotFoundException { - User user = userService.findById(userId) - .orElseThrow(() -> new UserNotFoundException("User not found with ID: " + userId)); - - return chatMessageService.getChatRoomIdsByUser(user); - } + @PostMapping("/image/convert") + public ResponseEntity> convertImageUrlToBase64(@RequestParam String imagePath) throws IOException { + byte[] imageBytes = chatMessageService.convertImageUrlToBytes(imagePath); - @GetMapping("/rooms/user/title/{userId}") - public List getChatRoomInfosByUserTitle(@PathVariable Long userId) throws UserNotFoundException { - User user = userService.findById(userId) - .orElseThrow(() -> new UserNotFoundException("User not found with ID: " + userId)); + HttpHeaders headers = new HttpHeaders(); + headers.set("Content-Type", "image/jpeg"); - return chatMessageService.getChatRoomInfosByUser(user); + return ResponseEntity.ok(ApiResponse.success(SuccessCode.OK, imageBytes)); } @DeleteMapping("/messages/{id}") - public void deleteMessage(@PathVariable Long id) { + public ResponseEntity> deleteMessage(@PathVariable Long id) { chatMessageService.deleteMessage(id); + return ResponseEntity.ok(ApiResponse.success(SuccessCode.OK)); } } diff --git a/src/main/java/com/helpmeCookies/chat/controller/ChatRoomController.java b/src/main/java/com/helpmeCookies/chat/controller/ChatRoomController.java index a16fc44..9549447 100644 --- a/src/main/java/com/helpmeCookies/chat/controller/ChatRoomController.java +++ b/src/main/java/com/helpmeCookies/chat/controller/ChatRoomController.java @@ -1,18 +1,28 @@ package com.helpmeCookies.chat.controller; - +import com.helpmeCookies.chat.dto.ChatMessageDto; +import com.helpmeCookies.chat.dto.ChatRoomInfo; import com.helpmeCookies.chat.entity.ChatRoom; +import com.helpmeCookies.chat.entity.MessageType; import com.helpmeCookies.chat.service.ChatMessageService; import com.helpmeCookies.chat.service.ChatRoomService; import com.helpmeCookies.chat.util.ImageStorageUtil; +import com.helpmeCookies.global.ApiResponse.ApiResponse; +import com.helpmeCookies.global.ApiResponse.SuccessCode; import com.helpmeCookies.global.exception.user.UserNotFoundException; import com.helpmeCookies.user.entity.User; import com.helpmeCookies.user.service.UserService; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.List; +import java.util.stream.Collectors; + @RestController @RequiredArgsConstructor +@Slf4j @RequestMapping("/v1/chat/rooms") public class ChatRoomController { private final ChatRoomService chatRoomService; @@ -21,7 +31,7 @@ public class ChatRoomController { private final ChatMessageService chatMessageService; @PostMapping - public ChatRoom createChatRoom( + public ResponseEntity> createChatRoom( @RequestParam String userEmail1, @RequestParam String userEmail2 ) throws UserNotFoundException { @@ -30,23 +40,51 @@ public ChatRoom createChatRoom( User user2 = userService.findByEmail(userEmail2) .orElseThrow(() -> new UserNotFoundException("User not found: " + userEmail2)); - ChatRoom chatRoom = chatRoomService.createChatRoom(user1, user2); String welcomeMessageContent = "Welcome, " + user2.getEmail() + "!"; - chatMessageService.saveMessage(chatRoom, user1, welcomeMessageContent); + ChatMessageDto chatMessageDto = new ChatMessageDto(user1.getEmail(), welcomeMessageContent, MessageType.ENTER); + chatMessageService.saveMessage(chatRoom.getId(), chatMessageDto); - return chatRoom; + return ResponseEntity.ok(ApiResponse.success(SuccessCode.OK, chatRoom)); } @GetMapping("/{chatRoomId}") - public ChatRoom getChatRoom(@PathVariable Long chatRoomId) { - return chatRoomService.getChatRoomById(chatRoomId); + public ResponseEntity> getChatRoom(@PathVariable Long chatRoomId) { + ChatRoom chatRoom = chatRoomService.getChatRoomById(chatRoomId); + return ResponseEntity.ok(ApiResponse.success(SuccessCode.OK, chatRoom)); } @DeleteMapping("/{chatRoomId}") - public void deleteChatRoom(@PathVariable Long chatRoomId) { + public ResponseEntity> deleteChatRoom(@PathVariable Long chatRoomId) { chatRoomService.deleteChatRoom(chatRoomId); imageStorageUtil.deleteChatFolder("chatRoom_" + chatRoomId); + + return ResponseEntity.ok(ApiResponse.success(SuccessCode.OK)); + } + + @GetMapping("/user/{userId}") + public ResponseEntity>> getUserChatRooms(@PathVariable Long userId) { + List chatRooms = chatRoomService.getChatRoomsByUserId(userId).stream() + .map(chatRoom -> new ChatRoomInfo(chatRoom.getId(), chatRoom.getTitle())) + .collect(Collectors.toList()); + + return ResponseEntity.ok(ApiResponse.success(SuccessCode.OK, chatRooms)); + } + + @PatchMapping("/{chatRoomId}/title") + public ResponseEntity> setChatRoomTitle( + @PathVariable Long chatRoomId, + @RequestParam Long userId, + @RequestParam String title + ) { + chatRoomService.setChatRoomTitleIfUserMatches(chatRoomId, userId, title); + return ResponseEntity.ok(ApiResponse.success(SuccessCode.OK)); + } + + @GetMapping + public ResponseEntity>> getAllChatRooms() { + List chatRooms = chatRoomService.getAllChatRooms(); + return ResponseEntity.ok(ApiResponse.success(SuccessCode.OK, chatRooms)); } } diff --git a/src/main/java/com/helpmeCookies/chat/controller/WebSocketChatController.java b/src/main/java/com/helpmeCookies/chat/controller/WebSocketChatController.java index a8c6220..c2f2d6a 100644 --- a/src/main/java/com/helpmeCookies/chat/controller/WebSocketChatController.java +++ b/src/main/java/com/helpmeCookies/chat/controller/WebSocketChatController.java @@ -1,90 +1,85 @@ package com.helpmeCookies.chat.controller; -import com.helpmeCookies.chat.dto.ImageMessageDTO; +import com.helpmeCookies.chat.dto.ChatMessageDto; import com.helpmeCookies.chat.entity.ChatMessage; import com.helpmeCookies.chat.entity.ChatRoom; +import com.helpmeCookies.chat.entity.MessageType; import com.helpmeCookies.chat.service.ChatMessageService; import com.helpmeCookies.chat.service.ChatRoomService; -import com.helpmeCookies.chat.util.ImageStorageUtil; import com.helpmeCookies.global.exception.user.UserNotFoundException; -import com.helpmeCookies.user.entity.User; -import com.helpmeCookies.user.service.UserService; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; +import lombok.extern.slf4j.Slf4j; import org.springframework.messaging.handler.annotation.DestinationVariable; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.simp.SimpMessageSendingOperations; -import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.messaging.simp.annotation.SubscribeMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.multipart.MultipartFile; -import java.io.File; import java.io.IOException; +import java.util.List; +@Slf4j @RestController -@RequestMapping("/v1/websocket") public class WebSocketChatController { private final SimpMessageSendingOperations messagingTemplate; private final ChatMessageService chatMessageService; private final ChatRoomService chatRoomService; - private final UserService userService; - private final ImageStorageUtil imageStorageUtil; - public WebSocketChatController(SimpMessageSendingOperations messagingTemplate, ChatMessageService chatMessageService, ChatRoomService chatRoomService, UserService userService, ImageStorageUtil imageStorageUtil) { + + public WebSocketChatController(SimpMessageSendingOperations messagingTemplate, + ChatMessageService chatMessageService, + ChatRoomService chatRoomService) { this.messagingTemplate = messagingTemplate; this.chatMessageService = chatMessageService; this.chatRoomService = chatRoomService; - this.userService = userService; - this.imageStorageUtil = imageStorageUtil; + } @MessageMapping("/chat/{chatRoomId}") - @Operation(summary = "채팅 메시지 전송", description = "WebSocket을 통해 특정 채팅방에 텍스트 메시지를 전송합니다.") - @Parameter(name = "chatRoomId", description = "채팅방 ID", required = true, schema = @Schema(type = "long")) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "성공적으로 메시지를 전송했습니다."), - @ApiResponse(responseCode = "404", description = "사용자를 찾을 수 없습니다.", content = @Content) - }) - public void chat(@DestinationVariable Long chatRoomId, - @Parameter(description = "전송할 채팅 메시지", required = true) ChatMessage message) throws UserNotFoundException { - ChatRoom chatRoom = chatRoomService.getChatRoomById(chatRoomId); - User sender = userService.findByEmail(message.getSender().getEmail()) - .orElseThrow(() -> new UserNotFoundException("발신자를 찾을 수 없습니다: " + message.getSender().getEmail())); + public void chat(@DestinationVariable Long chatRoomId, @RequestBody ChatMessageDto messageDto) { + ChatMessage savedMessage = chatMessageService.saveMessage(chatRoomId, messageDto); - chatMessageService.saveMessage(chatRoom, sender, message.getContent()); - messagingTemplate.convertAndSend("/api/sub/chat/rooms/" + chatRoomId, message); + messagingTemplate.convertAndSend("/v1/sub/chat/rooms/" + chatRoomId, savedMessage); } @MessageMapping("/chat/{chatRoomId}/file") @Operation(summary = "파일 전송", description = "WebSocket을 통해 특정 채팅방에 파일을 전송합니다.") - @Parameter(name = "chatRoomId", description = "채팅방 ID", required = true, schema = @Schema(type = "long")) - @Parameter(name = "file", description = "전송할 파일", required = true, schema = @Schema(type = "string", format = "binary")) - @Parameter(name = "userEmail", description = "발신자 이메일", required = true, schema = @Schema(type = "string")) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "성공적으로 파일을 전송했습니다."), - @ApiResponse(responseCode = "404", description = "사용자를 찾을 수 없습니다.", content = @Content) - }) public void sendFile(@DestinationVariable Long chatRoomId, - @RequestParam("file") MultipartFile file, - @RequestParam String userEmail) - throws UserNotFoundException, IOException { - ChatRoom chatRoom = chatRoomService.getChatRoomById(chatRoomId); - User sender = userService.findByEmail(userEmail) - .orElseThrow(() -> new UserNotFoundException("발신자를 찾을 수 없습니다: " + userEmail)); + @RequestParam String fileBase64, + @RequestParam String userEmail) { + try { + ChatMessage message = chatMessageService.saveFileMessage(chatRoomId, userEmail, fileBase64); - ChatMessage message = chatMessageService.saveFileMessage(chatRoom, sender, file); - String imagePath = message.getImageUrl(); - byte[] imageBytes = java.nio.file.Files.readAllBytes(new File(imagePath).toPath()); + byte[] imageBytes = chatMessageService.convertImageUrlToBytes(message.getContent()); + String encodedContent = ChatMessageDto.getImageContent(imageBytes); - ImageMessageDTO imageMessageDTO = new ImageMessageDTO(message, imageBytes); - messagingTemplate.convertAndSend("/api/sub/chat/rooms/" + chatRoomId, imageMessageDTO); + ChatMessageDto chatMessageDto = new ChatMessageDto( + message.getChatRoom().getId(), + message.getSender().getEmail(), + encodedContent, + message.getTimestamp().toString(), + MessageType.IMAGE + ); + + messagingTemplate.convertAndSend("/api/sub/chat/rooms/" + chatRoomId, chatMessageDto); + } catch (UserNotFoundException | IOException e) { + + log.error("파일 전송 중 오류 발생: " + e.getMessage(), e); + } } + + + @SubscribeMapping("/chat/rooms/{chatRoomId}/list") + public List sendInitialMessages(@DestinationVariable Long chatRoomId) { + ChatRoom chatRoom = chatRoomService.getChatRoomById(chatRoomId); + + return chatMessageService.getMessagesByChatRoom(chatRoom); + } + + } \ No newline at end of file diff --git a/src/main/java/com/helpmeCookies/chat/dto/ChatMessageDto.java b/src/main/java/com/helpmeCookies/chat/dto/ChatMessageDto.java new file mode 100644 index 0000000..eb85226 --- /dev/null +++ b/src/main/java/com/helpmeCookies/chat/dto/ChatMessageDto.java @@ -0,0 +1,38 @@ +package com.helpmeCookies.chat.dto; + +import com.helpmeCookies.chat.entity.MessageType; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ChatMessageDto { + private Long chatRoomId; + private String sender; + private String content; + private String timestamp; + private MessageType messageType; + + public ChatMessageDto() { + } + + public ChatMessageDto(Long chatRoomId, String sender, String content, String timestamp, MessageType messageType) { + this.chatRoomId = chatRoomId; + this.sender = sender; + this.content = content; + this.timestamp = timestamp; + this.messageType = messageType; + } + + public ChatMessageDto(String sender, String content, MessageType messageType) { + this.sender = sender; + this.content = content; + this.messageType = messageType; + } + + public static String getImageContent(byte[] contentBytes) { + return "data:image/base64:," + java.util.Base64.getEncoder().encodeToString(contentBytes); + } + + +} diff --git a/src/main/java/com/helpmeCookies/chat/dto/ChatRoomInfo.java b/src/main/java/com/helpmeCookies/chat/dto/ChatRoomInfo.java index 91f6a7f..b52dbf6 100644 --- a/src/main/java/com/helpmeCookies/chat/dto/ChatRoomInfo.java +++ b/src/main/java/com/helpmeCookies/chat/dto/ChatRoomInfo.java @@ -1,5 +1,10 @@ package com.helpmeCookies.chat.dto; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter public class ChatRoomInfo { private Long id; private String title; @@ -9,11 +14,4 @@ public ChatRoomInfo(Long id, String title) { this.title = title; } - public Long getId() { - return id; - } - - public String getTitle() { - return title; - } } \ No newline at end of file diff --git a/src/main/java/com/helpmeCookies/chat/dto/ImageMessageDTO.java b/src/main/java/com/helpmeCookies/chat/dto/ImageMessageDTO.java index dd71143..e8e18a5 100644 --- a/src/main/java/com/helpmeCookies/chat/dto/ImageMessageDTO.java +++ b/src/main/java/com/helpmeCookies/chat/dto/ImageMessageDTO.java @@ -2,6 +2,7 @@ import com.helpmeCookies.chat.entity.ChatMessage; +import com.helpmeCookies.chat.entity.MessageType; import lombok.Getter; import lombok.Setter; @@ -9,11 +10,13 @@ @Setter public class ImageMessageDTO { private ChatMessage chatMessage; - private byte[] imageData; + private String imageBase64; // Base64로 인코딩된 이미지 데이터 + private MessageType messageType; // 메시지 타입 - public ImageMessageDTO(ChatMessage chatMessage, byte[] imageData) { + public ImageMessageDTO(ChatMessage chatMessage, byte[] imageData, MessageType messageType) { this.chatMessage = chatMessage; - this.imageData = imageData; + this.imageBase64 = "data:image/png;base64," + java.util.Base64.getEncoder().encodeToString(imageData); + this.messageType = messageType; } } diff --git a/src/main/java/com/helpmeCookies/chat/entity/ChatMessage.java b/src/main/java/com/helpmeCookies/chat/entity/ChatMessage.java index 95ba0e7..469712c 100644 --- a/src/main/java/com/helpmeCookies/chat/entity/ChatMessage.java +++ b/src/main/java/com/helpmeCookies/chat/entity/ChatMessage.java @@ -6,6 +6,7 @@ import java.time.LocalDateTime; + @Entity @Table(name = "chat_messages") public class ChatMessage { @@ -22,34 +23,30 @@ public class ChatMessage { @JoinColumn(name = "user_id", nullable = false) private User sender; - //private MessageType type; + private String content; // 내용 (텍스트 메시지에 사용) + + private LocalDateTime timestamp; - private String content; //내용 + @Enumerated(EnumType.STRING) + @Column(name = "message_type") + private MessageType messageType; + /* @Column(name = "image_url") - private String imageUrl; // 이미지 URL + private String imageUrl; // 이미지 URL (이미지 메시지에 사용) - private LocalDateTime timestamp; + */ protected ChatMessage() {} - public ChatMessage(ChatRoom chatRoom, User sender, String content) { + public ChatMessage(ChatRoom chatRoom, User sender, String content, MessageType messageType) { this.chatRoom = chatRoom; this.sender = sender; - this.content = content; + this.content = content != null ? content : ""; // 텍스트가 없으면 빈 문자열로 처리 + this.messageType = messageType; this.timestamp = LocalDateTime.now(); } - public ChatMessage(ChatRoom chatRoom, User sender, String content, String imageUrl) { - this.chatRoom = chatRoom; - this.sender = sender; - this.content = content; - this.imageUrl = imageUrl; - this.timestamp = LocalDateTime.now(); - } - - - // Getters and Setters public Long getId() { return id; @@ -67,15 +64,15 @@ public String getContent() { return content; } - public String getImageUrl() { - return imageUrl; - } - public LocalDateTime getTimestamp() { return timestamp; } - public void setImageUrl(String imageUrl) { - this.imageUrl = imageUrl; + public MessageType getMessageType() { + return messageType; + } + + public void setMessageType(MessageType messageType) { + this.messageType = messageType; } } diff --git a/src/main/java/com/helpmeCookies/chat/entity/ChatRoom.java b/src/main/java/com/helpmeCookies/chat/entity/ChatRoom.java index f74cc48..c98bf8c 100644 --- a/src/main/java/com/helpmeCookies/chat/entity/ChatRoom.java +++ b/src/main/java/com/helpmeCookies/chat/entity/ChatRoom.java @@ -32,4 +32,8 @@ public ChatRoom(User user1, User user2) { this.user1 = user1; this.user2 = user2; } + + public void updateTitle(String title) { + this.title = title; + } } diff --git a/src/main/java/com/helpmeCookies/chat/entity/MessageType.java b/src/main/java/com/helpmeCookies/chat/entity/MessageType.java index b1df7a9..fcecb89 100644 --- a/src/main/java/com/helpmeCookies/chat/entity/MessageType.java +++ b/src/main/java/com/helpmeCookies/chat/entity/MessageType.java @@ -1,5 +1,5 @@ package com.helpmeCookies.chat.entity; public enum MessageType { - ENTER, TALK, EXIT, MATCH, MATCH_REQUEST; + IMAGE, TEXT, ENTER, TALK, EXIT; } diff --git a/src/main/java/com/helpmeCookies/chat/repository/ChatMessageRepository.java b/src/main/java/com/helpmeCookies/chat/repository/ChatMessageRepository.java index b8a78c3..1e80b53 100644 --- a/src/main/java/com/helpmeCookies/chat/repository/ChatMessageRepository.java +++ b/src/main/java/com/helpmeCookies/chat/repository/ChatMessageRepository.java @@ -1,22 +1,13 @@ package com.helpmeCookies.chat.repository; -import com.helpmeCookies.chat.dto.ChatRoomInfo; import com.helpmeCookies.chat.entity.ChatMessage; import com.helpmeCookies.chat.entity.ChatRoom; -import com.helpmeCookies.user.entity.User; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; - import java.util.List; public interface ChatMessageRepository extends JpaRepository { - // 특정 채팅방의 메시지들을 시간순으로 정렬하여 반환하는 메서드 List findByChatRoomOrderByTimestampAsc(ChatRoom chatRoom); - //특정 유저의 채팅룸 ID를 조회 - List findBySender(User sender); - //특정 유저의 채팅룸 id와 제목을 같이 반환한다. - @Query("SELECT new com.helpmeCookies.chat.dto.ChatRoomInfo(cm.chatRoom.id, cm.chatRoom.title) FROM ChatMessage cm WHERE cm.sender = :user GROUP BY cm.chatRoom.id, cm.chatRoom.title") - List findChatRoomInfosByUser(User user); + void deleteByChatRoom(ChatRoom chatRoom); } diff --git a/src/main/java/com/helpmeCookies/chat/repository/ChatRoomRepository.java b/src/main/java/com/helpmeCookies/chat/repository/ChatRoomRepository.java index 4e94aad..ddb5125 100644 --- a/src/main/java/com/helpmeCookies/chat/repository/ChatRoomRepository.java +++ b/src/main/java/com/helpmeCookies/chat/repository/ChatRoomRepository.java @@ -4,7 +4,17 @@ import com.helpmeCookies.chat.entity.ChatRoom; import com.helpmeCookies.user.entity.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.Optional; public interface ChatRoomRepository extends JpaRepository { - ChatRoom findByUser1AndUser2(User user1, User user2); + @Query("SELECT c FROM ChatRoom c WHERE (c.user1 = :user1 AND c.user2 = :user2) OR (c.user1 = :user2 AND c.user2 = :user1)") + Optional findByUser1AndUser2(@Param("user1") User user1, @Param("user2") User user2); + + @Query("SELECT c FROM ChatRoom c WHERE c.user1.id = :userId OR c.user2.id = :userId") + List findByUserId(@Param("userId") Long userId); } + diff --git a/src/main/java/com/helpmeCookies/chat/service/ChatMessageService.java b/src/main/java/com/helpmeCookies/chat/service/ChatMessageService.java index 7fe53da..f056112 100644 --- a/src/main/java/com/helpmeCookies/chat/service/ChatMessageService.java +++ b/src/main/java/com/helpmeCookies/chat/service/ChatMessageService.java @@ -1,17 +1,27 @@ package com.helpmeCookies.chat.service; +import com.helpmeCookies.chat.dto.ChatMessageDto; import com.helpmeCookies.chat.dto.ChatRoomInfo; import com.helpmeCookies.chat.entity.ChatMessage; import com.helpmeCookies.chat.entity.ChatRoom; +import com.helpmeCookies.chat.entity.MessageType; import com.helpmeCookies.chat.repository.ChatMessageRepository; +import com.helpmeCookies.chat.repository.ChatRoomRepository; import com.helpmeCookies.chat.util.ImageStorageUtil; +import com.helpmeCookies.global.exception.user.UserNotFoundException; import com.helpmeCookies.user.entity.User; +import com.helpmeCookies.user.repository.UserRepository; +import com.helpmeCookies.user.service.UserService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.util.Base64; import java.util.List; import java.util.stream.Collectors; @@ -20,44 +30,57 @@ public class ChatMessageService { private final ChatMessageRepository chatMessageRepository; private final ImageStorageUtil imageStorageUtil; + private final ChatRoomRepository chatRoomRepository; + private final UserRepository userRepository; + private final ChatRoomService chatRoomService; + private final UserService userService; + + @Transactional + public ChatMessage saveMessage(Long chatRoomId, ChatMessageDto messageDto) { + ChatRoom chatRoom = chatRoomRepository.findById(chatRoomId) + .orElseThrow(() -> new RuntimeException("채팅방을 찾을 수 없습니다.")); + + User sender = userService.findByEmail(messageDto.getSender()) + .orElseThrow(() -> new RuntimeException("사용자를 찾을 수 없습니다.")); + + ChatMessage message = new ChatMessage(chatRoom, sender, messageDto.getContent(), messageDto.getMessageType()); - public ChatMessage saveMessage(ChatRoom chatRoom, User sender, String content) { - ChatMessage message = new ChatMessage(chatRoom, sender, content); return chatMessageRepository.save(message); } - public void deleteMessage(Long messageId) { - chatMessageRepository.deleteById(messageId); - } + @Transactional + public ChatMessage saveFileMessage(Long chatRoomId, String userEmail, String fileBase64) throws IOException, UserNotFoundException { + ChatRoom chatRoom = chatRoomService.getChatRoomById(chatRoomId); + User sender = userService.findByEmail(userEmail) + .orElseThrow(() -> new UserNotFoundException("발신자를 찾을 수 없습니다: " + userEmail)); - public ChatMessage saveFileMessage(ChatRoom chatRoom, User sender, MultipartFile file) throws IOException { - // 파일 저장 및 URL 반환 String folderPath = "chatRoom_" + chatRoom.getId(); - String imageUrl = imageStorageUtil.saveChatImage(file, folderPath); + String imageUrl = imageStorageUtil.saveBase64Image(fileBase64, folderPath); // 공통 메서드를 사용하여 저장 - // 메시지 생성 (URL만 포함) - ChatMessage message = new ChatMessage(chatRoom, sender, "image", imageUrl); + ChatMessage message = new ChatMessage(chatRoom, sender, imageUrl, MessageType.IMAGE); - return chatMessageRepository.save(message); // 메시지 저장 + return chatMessageRepository.save(message); } - // 특정 채팅방의 메시지를 시간 순서대로 가져오는 메서드 - public List getMessagesByChatRoom(ChatRoom chatRoom) { - return chatMessageRepository.findByChatRoomOrderByTimestampAsc(chatRoom); + public byte[] convertImageUrlToBytes(String imagePath) throws IOException { + File imageFile = new File(imagePath); + return Files.readAllBytes(imageFile.toPath()); } - // 특정 유저의 채팅룸 ID를 반환하는 메서드 - public List getChatRoomIdsByUser(User user) { - List messages = chatMessageRepository.findBySender(user); - return messages.stream() - .map(message -> message.getChatRoom().getId()) - .distinct() // 중복 제거 - .collect(Collectors.toList()); + public String convertBytesToBase64(byte[] imageBytes) { + return Base64.getEncoder().encodeToString(imageBytes); + } + + public void deleteMessage(Long messageId) { + chatMessageRepository.deleteById(messageId); + } + + public List getMessagesByChatRoom(ChatRoom chatRoom) { + return chatMessageRepository.findByChatRoomOrderByTimestampAsc(chatRoom); } - // 특정 유저의 채팅룸 ID와 제목을 반환하는 메서드 - public List getChatRoomInfosByUser(User user) { - return chatMessageRepository.findChatRoomInfosByUser(user); + public List getAllMessages() { + return chatMessageRepository.findAll(); } } diff --git a/src/main/java/com/helpmeCookies/chat/service/ChatRoomService.java b/src/main/java/com/helpmeCookies/chat/service/ChatRoomService.java index 0334f21..65b1927 100644 --- a/src/main/java/com/helpmeCookies/chat/service/ChatRoomService.java +++ b/src/main/java/com/helpmeCookies/chat/service/ChatRoomService.java @@ -2,26 +2,47 @@ import com.helpmeCookies.chat.entity.ChatRoom; +import com.helpmeCookies.chat.repository.ChatMessageRepository; import com.helpmeCookies.chat.repository.ChatRoomRepository; import com.helpmeCookies.global.exception.chat.ChatRoomNotFoundException; import com.helpmeCookies.user.entity.User; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.util.List; import java.util.Optional; @Service @RequiredArgsConstructor public class ChatRoomService { private final ChatRoomRepository chatRoomRepository; + private final ChatMessageRepository chatMessageRepository; // 추가된 부분 + + @Transactional + public void deleteChatRoom(Long id) { + ChatRoom chatRoom = chatRoomRepository.findById(id) + .orElseThrow(() -> new ChatRoomNotFoundException("Chat room not found with ID: " + id)); + + chatMessageRepository.deleteByChatRoom(chatRoom); // 채팅방에 속한 모든 메시지 삭제 + + chatRoomRepository.delete(chatRoom); + } public ChatRoom createChatRoom(User user1, User user2) { + + Optional existingChatRoom = chatRoomRepository.findByUser1AndUser2(user1, user2); + if (existingChatRoom.isPresent()) { + return existingChatRoom.get(); + } + ChatRoom chatRoom = new ChatRoom(user1, user2); return chatRoomRepository.save(chatRoom); } - public ChatRoom getChatRoom(User user1, User user2) { - return chatRoomRepository.findByUser1AndUser2(user1, user2); + public Optional getChatRoom(User user1, User user2) { + return Optional.ofNullable(chatRoomRepository.findByUser1AndUser2(user1, user2)) + .orElseThrow(() -> new ChatRoomNotFoundException("채팅방이 존재하지 않습니다.")); } public Optional findById(Long id) { @@ -33,11 +54,24 @@ public ChatRoom getChatRoomById(Long id) { .orElseThrow(() -> new ChatRoomNotFoundException("Chat room not found with ID: " + id)); } + public List getChatRoomsByUserId(Long userId) { + return chatRoomRepository.findByUserId(userId); + } - // deleteChatRoom 메서드 추가 - public void deleteChatRoom(Long id) { - ChatRoom chatRoom = chatRoomRepository.findById(id) - .orElseThrow(() -> new ChatRoomNotFoundException("Chat room not found with ID: " + id)); - chatRoomRepository.delete(chatRoom); + @Transactional + public void setChatRoomTitleIfUserMatches(Long chatRoomId, Long userId, String title) { + ChatRoom chatRoom = chatRoomRepository.findById(chatRoomId) + .orElseThrow(() -> new ChatRoomNotFoundException("해당 ID의 채팅방을 찾을 수 없습니다: " + chatRoomId)); + + if (chatRoom.getUser1().getId().equals(userId) || chatRoom.getUser2().getId().equals(userId)) { + + chatRoom.updateTitle(title); + } else { + throw new IllegalArgumentException("유저 ID가 채팅방 참가자와 일치하지 않습니다."); + } + } + + public List getAllChatRooms() { + return chatRoomRepository.findAll(); } -} +} \ No newline at end of file diff --git a/src/main/java/com/helpmeCookies/chat/util/ImageStorageUtil.java b/src/main/java/com/helpmeCookies/chat/util/ImageStorageUtil.java index 2e36960..8f6add9 100644 --- a/src/main/java/com/helpmeCookies/chat/util/ImageStorageUtil.java +++ b/src/main/java/com/helpmeCookies/chat/util/ImageStorageUtil.java @@ -25,10 +25,11 @@ public static String saveImage(MultipartFile imageFile) throws IOException { // ClassPathResource를 사용하여 리소스 경로를 얻습니다. ClassPathResource resource = new ClassPathResource(STORAGE_DIR); + // 실제 파일 저장 경로를 지정합니다. File storageDir = new File(resource.getPath()); if (!storageDir.exists()) { - storageDir.mkdirs(); + storageDir.mkdirs(); // 디렉토리가 존재하지 않으면 생성합니다. } File outputFile = new File(storageDir, imageName); @@ -82,6 +83,25 @@ public String saveChatImage(MultipartFile imageFile, String folderPath) throws I return filePath; } + // Base64 데이터를 이미지 파일로 저장하는 공통 메서드 + public String saveBase64Image(String fileBase64, String folderPath) throws IOException { + byte[] decodedBytes = Base64.getDecoder().decode(fileBase64); + String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")); + String imageName = "image_" + timestamp + ".jpg"; + + File storageDir = new File(STORAGE_DIR + folderPath); + if (!storageDir.exists()) { + storageDir.mkdirs(); + } + + File outputFile = new File(storageDir, imageName); + try (FileOutputStream fos = new FileOutputStream(outputFile)) { + fos.write(decodedBytes); + } + + return outputFile.getAbsolutePath(); // 파일 경로 반환 + } + // 채팅방 이미지 폴더 삭제 메서드 public void deleteChatFolder(String folderPath) { File folder = new File(STORAGE_DIR + folderPath); diff --git a/src/main/java/com/helpmeCookies/global/config/WebConfig.java b/src/main/java/com/helpmeCookies/global/config/WebConfig.java index 8cefb75..76eef55 100644 --- a/src/main/java/com/helpmeCookies/global/config/WebConfig.java +++ b/src/main/java/com/helpmeCookies/global/config/WebConfig.java @@ -1,6 +1,8 @@ package com.helpmeCookies.global.config; - +import java.util.Arrays; +import java.util.List; +import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; diff --git a/src/main/java/com/helpmeCookies/global/config/WebSocketConfig.java b/src/main/java/com/helpmeCookies/global/config/WebSocketConfig.java index d8254c2..3e0cfb8 100644 --- a/src/main/java/com/helpmeCookies/global/config/WebSocketConfig.java +++ b/src/main/java/com/helpmeCookies/global/config/WebSocketConfig.java @@ -11,13 +11,12 @@ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { - config.enableSimpleBroker("/api/sub"); - config.setApplicationDestinationPrefixes("/api/pub"); + config.enableSimpleBroker("/v1/sub"); + config.setApplicationDestinationPrefixes("/v1/pub"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { - registry.addEndpoint("/ws").setAllowedOriginPatterns("*"); - //.withSockJS(); + registry.addEndpoint("/ws").setAllowedOriginPatterns("*").withSockJS(); } } \ No newline at end of file diff --git a/src/main/java/com/helpmeCookies/global/security/WebSecurityConfig.java b/src/main/java/com/helpmeCookies/global/security/WebSecurityConfig.java index eeda844..8fee72f 100644 --- a/src/main/java/com/helpmeCookies/global/security/WebSecurityConfig.java +++ b/src/main/java/com/helpmeCookies/global/security/WebSecurityConfig.java @@ -86,7 +86,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { "/v1/products/**", "/v1/reviews/**", "/ws/**", - "/v1/artists/**" + "/v1/artists/**", + "v1/chat/**" ).permitAll() .anyRequest().authenticated() ).exceptionHandling((exception) -> exception