Skip to content

Commit

Permalink
Merge pull request #135 from kakao-tech-campus-2nd-step3/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
yooonwodyd authored Nov 15, 2024
2 parents 77ef08a + 9a2f2db commit 3c8d9e3
Show file tree
Hide file tree
Showing 17 changed files with 316 additions and 159 deletions.
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -25,33 +27,35 @@ public class ChatMessageController {
private final UserService userService;
private final ImageStorageUtil imageStorageUtil;

@GetMapping("/messages")
public ResponseEntity<ApiResponse<List<ChatMessage>>> getAllMessages() {
List<ChatMessage> messages = chatMessageService.getAllMessages();
return ResponseEntity.ok(ApiResponse.success(SuccessCode.OK, messages));
}

@GetMapping("/rooms/{chatRoomId}/messages")
public List<ChatMessage> getMessagesByChatRoom(@PathVariable Long chatRoomId) {
public ResponseEntity<ApiResponse<List<ChatMessage>>> getMessagesByChatRoom(@PathVariable Long chatRoomId) {
ChatRoom chatRoom = chatRoomService.findById(chatRoomId)
.orElseThrow(() -> new ChatRoomIdNotFoundException(chatRoomId));

return chatMessageService.getMessagesByChatRoom(chatRoom);
List<ChatMessage> messages = chatMessageService.getMessagesByChatRoom(chatRoom);
return ResponseEntity.ok(ApiResponse.success(SuccessCode.OK, messages));
}

@GetMapping("/rooms/user/{userId}")
public List<Long> 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<ApiResponse<byte[]>> convertImageUrlToBase64(@RequestParam String imagePath) throws IOException {
byte[] imageBytes = chatMessageService.convertImageUrlToBytes(imagePath);

@GetMapping("/rooms/user/title/{userId}")
public List<ChatRoomInfo> 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<ApiResponse<Void>> deleteMessage(@PathVariable Long id) {
chatMessageService.deleteMessage(id);
return ResponseEntity.ok(ApiResponse.success(SuccessCode.OK));
}
}

Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -21,7 +31,7 @@ public class ChatRoomController {
private final ChatMessageService chatMessageService;

@PostMapping
public ChatRoom createChatRoom(
public ResponseEntity<ApiResponse<ChatRoom>> createChatRoom(
@RequestParam String userEmail1,
@RequestParam String userEmail2
) throws UserNotFoundException {
Expand All @@ -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<ApiResponse<ChatRoom>> 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<ApiResponse<Void>> deleteChatRoom(@PathVariable Long chatRoomId) {
chatRoomService.deleteChatRoom(chatRoomId);
imageStorageUtil.deleteChatFolder("chatRoom_" + chatRoomId);

return ResponseEntity.ok(ApiResponse.success(SuccessCode.OK));
}

@GetMapping("/user/{userId}")
public ResponseEntity<ApiResponse<List<ChatRoomInfo>>> getUserChatRooms(@PathVariable Long userId) {
List<ChatRoomInfo> 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<ApiResponse<Void>> 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<ApiResponse<List<ChatRoom>>> getAllChatRooms() {
List<ChatRoom> chatRooms = chatRoomService.getAllChatRooms();
return ResponseEntity.ok(ApiResponse.success(SuccessCode.OK, chatRooms));
}
}
Original file line number Diff line number Diff line change
@@ -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<ChatMessage> sendInitialMessages(@DestinationVariable Long chatRoomId) {
ChatRoom chatRoom = chatRoomService.getChatRoomById(chatRoomId);

return chatMessageService.getMessagesByChatRoom(chatRoom);
}


}
38 changes: 38 additions & 0 deletions src/main/java/com/helpmeCookies/chat/dto/ChatMessageDto.java
Original file line number Diff line number Diff line change
@@ -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);
}


}
12 changes: 5 additions & 7 deletions src/main/java/com/helpmeCookies/chat/dto/ChatRoomInfo.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -9,11 +14,4 @@ public ChatRoomInfo(Long id, String title) {
this.title = title;
}

public Long getId() {
return id;
}

public String getTitle() {
return title;
}
}
9 changes: 6 additions & 3 deletions src/main/java/com/helpmeCookies/chat/dto/ImageMessageDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,21 @@


import com.helpmeCookies.chat.entity.ChatMessage;
import com.helpmeCookies.chat.entity.MessageType;
import lombok.Getter;
import lombok.Setter;

@Getter
@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;
}
}

Loading

0 comments on commit 3c8d9e3

Please sign in to comment.