Skip to content

Commit

Permalink
[채팅] 채팅 방 목록 조회, 생성 등 (#86)
Browse files Browse the repository at this point in the history
* feat: 채팅방 관련 api

* feat: 채팅방, 채팅 메시지 엔티티 생성(#75)

* feat: 채팅방 생성(#75)

* feat: 체팅 메시지 엔티티에 채팅 방 추가(#75)

* feat: 채팅방 목록 조회 쿼리 생성(#75)

* feat: 채팅방 목록 조회 api 생성(#75)

* feat: 채팅 요청 시 입장 메시지 추가(#75)

* feat: 채팅 요청 수락(#75)

* chore: 주석 추가(#75)

* feat: sender, receiver로 변수명 통일(#75)

* fix: 채팅 및 채팅방 생성과 알림 순서 수정(#75)

* fix: sender, receiver로 변수명 통일(#75)
  • Loading branch information
acceptor-gyu authored May 18, 2024
1 parent 8bbaade commit 0c72062
Show file tree
Hide file tree
Showing 27 changed files with 582 additions and 170 deletions.
116 changes: 42 additions & 74 deletions be/src/main/java/yeonba/be/chatting/controller/ChattingController.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,96 +5,64 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import org.springframework.http.MediaType;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import yeonba.be.chatting.dto.ChattingRoomResponse;
import yeonba.be.chatting.dto.request.ChattingSendMessageRequest;
import yeonba.be.chatting.dto.response.ChatRoomResponse;
import yeonba.be.chatting.service.ChatService;
import yeonba.be.util.CustomResponse;

@Tag(name = "Chatting", description = "채팅 API")
@RestController
@RequiredArgsConstructor
public class ChattingController {

@Operation(
summary = "채팅 목록 조회",
description = "자신이 참여 중인 채팅 목록을 조회할 수 있습니다."
)
@ApiResponse(
responseCode = "200",
description = "참여 중인 채팅 목록 조회 성공"
)
@GetMapping("/chattings")
public ResponseEntity<CustomResponse<List<ChattingRoomResponse>>> chattings() {
private final ChatService chatService;

return ResponseEntity
.ok()
.body(new CustomResponse<>());
}
@Operation(summary = "채팅 목록 조회", description = "자신이 참여 중인 채팅 목록을 조회할 수 있습니다.")
@ApiResponse(responseCode = "200", description = "참여 중인 채팅 목록 조회 성공")
@GetMapping("/chattings")
public ResponseEntity<CustomResponse<List<ChatRoomResponse>>> getChatRooms(
@RequestAttribute("userId") long userId) {

@Operation(
summary = "채팅 요청",
description = "다른 사용자에게 채팅을 요청할 수 있습니다."
)
@ApiResponse(
responseCode = "200",
description = "채팅 요청 정상 처리"
)
@PostMapping("/users/{userId}/chat")
public ResponseEntity<CustomResponse<Void>> requestChat(
@Parameter(description = "사용자 ID", example = "1")
@PathVariable long userId) {
List<ChatRoomResponse> response = chatService.getChatRooms(userId);

return ResponseEntity
.ok()
.body(new CustomResponse<>());
}
return ResponseEntity
.ok()
.body(new CustomResponse<>(response));
}

@Operation(
summary = "채팅 메시지 전송",
description = "단순 텍스트 형식 채팅 메시지를 전송할 수 있습니다."
)
@ApiResponse(
responseCode = "202",
description = "채팅 메시지 전송 정상 처리"
)
@PostMapping("/chattings/{chattingId}/message")
public ResponseEntity<CustomResponse<Void>> sendMessage(
@Parameter(description = "채팅방 ID", example = "1")
@PathVariable long chattingId,
@RequestBody ChattingSendMessageRequest request) {
@Operation(summary = "채팅 요청", description = "다른 사용자에게 채팅을 요청할 수 있습니다.")
@ApiResponse(responseCode = "200", description = "채팅 요청 정상 처리")
@PostMapping("/users/{partnerId}/chat")
public ResponseEntity<CustomResponse<Void>> requestChat(
@RequestAttribute("userId") long userId,
@Parameter(description = "사용자 ID", example = "1")
@PathVariable long partnerId) {

return ResponseEntity
.accepted()
.body(new CustomResponse<>());
}
chatService.requestChat(userId, partnerId);

@Operation(
summary = "사진 메시지 전송",
description = "사진을 전송할 수 있습니다."
)
@ApiResponse(
responseCode = "202",
description = "사진 전송 정상 처리"
)
@PostMapping(
path = "/chattings/{chattingId}/photo",
consumes = MediaType.MULTIPART_FORM_DATA_VALUE
)
public ResponseEntity<CustomResponse<Void>> sendPhoto(
@Parameter(description = "채팅방 ID", example = "1")
@PathVariable long chattingId,
@Parameter(description = "전송 사진 파일")
@RequestPart(value = "photoFile") MultipartFile photoFile) {
return ResponseEntity
.ok()
.body(new CustomResponse<>());
}

return ResponseEntity
.accepted()
.body(new CustomResponse<>());
}
@Operation(summary = "채팅 요청 수락", description = "요청받은 채팅을 수락할 수 있습니다.")
@ApiResponse(responseCode = "200", description = "채팅 요청 수락 정상 처리")
@PostMapping("/notifications/{notificationId}/chat")
public ResponseEntity<CustomResponse<Void>> acceptRequestedChat(
@RequestAttribute("userId") long userId,
@Parameter(description = "알림 ID", example = "1")
@PathVariable long notificationId) {

chatService.acceptRequestedChat(userId, notificationId);

return ResponseEntity
.ok()
.body(new CustomResponse<>());
}
}
46 changes: 0 additions & 46 deletions be/src/main/java/yeonba/be/chatting/dto/ChattingRoomResponse.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
@AllArgsConstructor
public class ChattingSendMessageRequest {

@Schema(
type = "string",
description = "메시지 내용",
example = "밥 먹었어?"
)
private String content;
@Schema(
type = "string",
description = "메시지 내용",
example = "밥 먹었어?"
)
private String content;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package yeonba.be.chatting.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Getter;
import yeonba.be.chatting.entity.ChatRoom;

@Getter
@AllArgsConstructor
public class ChatRoomResponse {

@Schema(type = "number", description = "채팅방 ID", example = "1")
private long id;

@Schema(type = "string", description = "채팅 상대 이름", example = "김민재")
private String partnerName;

@Schema(type = "string", description = "채팅 상대 프로필 이미지 URL", example = "yeonba.com/profile")
private String partnerProfileImageUrl;

@Schema(type = "number", description = "읽지 않은 메시지 수", example = "25")
private int unreadMessageNumber;

@Schema(type = "string", description = "마지막 메시지", example = "잘 자!")
private String lastMessage;

@Schema(type = "string", description = "마지막 메시지 일시", example = "2022-10-11 13:20:15")
private LocalDateTime lastMessageAt;
}
64 changes: 64 additions & 0 deletions be/src/main/java/yeonba/be/chatting/entity/ChatMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package yeonba.be.chatting.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import yeonba.be.user.entity.User;

@Table(name = "chat_messages")
@Getter
@Entity
@EntityListeners(value = AuditingEntityListener.class)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ChatMessage {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "chat_room_id")
private ChatRoom chatRoom;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sent_user_id")
private User sender;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "received_user_id")
private User receiver;

private String content;

@Column(name = "is_read")
private boolean read;

private LocalDateTime sentAt;

@CreatedDate
private LocalDateTime createdAt;

private LocalDateTime deletedAt;

public ChatMessage(ChatRoom chatRoom, User sender, User receiver, String content) {

this.chatRoom = chatRoom;
this.sender = sender;
this.receiver = receiver;
this.content = content;
this.read = false;
}
}
64 changes: 64 additions & 0 deletions be/src/main/java/yeonba/be/chatting/entity/ChatRoom.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package yeonba.be.chatting.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import java.util.List;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import yeonba.be.user.entity.User;

@Table(name = "chat_rooms")
@Getter
@Entity
@EntityListeners(value = AuditingEntityListener.class)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@EqualsAndHashCode(of = "id")
public class ChatRoom {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sent_user_id")
private User sender;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "received_user_id")
private User receiver;

private boolean active;

@CreatedDate
private LocalDateTime createdAt;

private LocalDateTime deletedAt;

@OneToMany(mappedBy = "chatRoom")
private List<ChatMessage> chatMessages;

public ChatRoom(User sender, User receiver) {

this.sender = sender;
this.receiver = receiver;
this.active = false;
}

public void activeRoom() {

this.active = true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package yeonba.be.chatting.repository.chatmessage;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import yeonba.be.chatting.entity.ChatMessage;

@Component
@RequiredArgsConstructor
public class ChatMessageCommand {

private final ChatMessageRepository chatMessageRepository;

public ChatMessage createChatMessage(ChatMessage message) {

return chatMessageRepository.save(message);
}
}
Loading

0 comments on commit 0c72062

Please sign in to comment.