Skip to content

Commit

Permalink
QA를 위한 dev -> prod (#257)
Browse files Browse the repository at this point in the history
* hotfix/file-profileImg-1: File presignURL ID로 가져오기 작업 - ProfileImg (#253)

* Feat/single chatroom exit : 싱글 채팅방 퇴장 및 혼자 남아있을 경우 (상대방 퇴장 시)알림 구현 (#255)

* feat/singleChatroom-1: 싱글 채팅방 퇴장 구현

- 기존 채팅방 퇴장은 그룹 채팅방 퇴장만 구현되어 있음 -> 싱글 채팅방 퇴장도 추가 구현

- 그룹 채팅방은 Redisson 처리한 사항이 있어 DB 저장 작업이 필수적임 -> 구별되게 그룹 채팅방 퇴장과 싱글 채팅방 퇴장을 구분
- 채팅 퇴장 시 퇴장 채팅 저장과 Redis 발행은 기존대로 유지 (채팅 보내기와 동일하게 동작함)

* feat/singleChatroom-2: 채팅방 퇴장 시 혼자 남은 채팅방 알림구현

- 그룹, 싱글 알림 모두 구현
- 기존 알림 서비스와 동일
- Set의 members에서 한 명의 유저만 남아있을 경우 stream.findFirst() 사용함
- 사용자 언어설정에 따른 번역 알림 추가

* feat/singleChatroom-isRead-1: 싱글 채팅방 읽음 대상자(상대방) 읽었는지 표시 구현 (#256)

* feat/singleChatroom-isRead-
1: 싱글 채팅방 읽음 대상자(상대방) 읽었는지 표시 구현

- Chat 엔티티에 해당 Boolean 값인 isOtherRead 생성
- 읽음 대상자 (상대방)이 GET :chats?chatroomId={채팅방 ID}를 하면 해당 isOtherRead를 true로 바꿔줌

* hotfix/chatroom-bookmark-individual-1: 채팅방 별 북마크 조회 가능하도록 수정

* feat/singleChatroom-isRead-
2: 싱글 채팅방 퇴장 시 알림 구현 사항 되돌리기
- 이유 : 불필요
  • Loading branch information
KooSuYeon authored Oct 1, 2024
1 parent e37df5a commit 47cc7c9
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 51 deletions.
4 changes: 2 additions & 2 deletions src/main/java/com/dife/api/controller/BookmarkController.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ public ResponseEntity<BookmarkResponseDto> createBookmark(
return ResponseEntity.status(CREATED).body(responseDto);
}

@GetMapping("/{chatroomId}")
@GetMapping("/")
public ResponseEntity<List<BookmarkResponseDto>> getBookmarkChats(
@PathVariable(name = "chatroomId") Long chatroomId, Authentication authentication) {
@RequestParam(name = "chatroomId") Long chatroomId, Authentication authentication) {
List<BookmarkResponseDto> bookmarks =
bookmarkService.getChatroomBookmarks(chatroomId, authentication.getName());
return ResponseEntity.ok(bookmarks);
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/com/dife/api/handler/DisconnectHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ public boolean isFull(Chatroom chatroom) {
}

public boolean isEmpty(Chatroom chatroom) {
ChatroomSetting setting = chatroom.getChatroomSetting();
return setting.getCount() < 1;
return chatroom.getMembers().isEmpty();
}

public void disconnect(Long chatroomId, String sessionId) {
Expand Down
62 changes: 45 additions & 17 deletions src/main/java/com/dife/api/handler/NotificationHandler.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,59 @@
package com.dife.api.handler;

import com.dife.api.model.Chatroom;
import com.dife.api.model.ChatroomSetting;
import com.dife.api.model.*;
import com.dife.api.service.NotificationService;
import java.time.LocalDateTime;
import java.util.*;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;

@Configuration
@RequiredArgsConstructor
public class NotificationHandler {

private final SimpMessageSendingOperations messagingTemplate;
private final NotificationService notificationService;

public void isAlone(Chatroom chatroom, String sessionId) {
ChatroomSetting setting = chatroom.getChatroomSetting();
if (setting.getCount() < 2) {
notificate(chatroom.getId(), sessionId);
}
public void isAlone(Chatroom chatroom, Member exitMember) {
if (chatroom.getMembers().size() < 2 && chatroom.getChatroomType() == ChatroomType.GROUP)
notificate(chatroom, exitMember);
}

public void notificate(Long chatroomId, String sessionId) {
StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.MESSAGE);
accessor.setSessionId(sessionId);
accessor.setDestination("/sub/chatroom/" + chatroomId);
messagingTemplate.convertAndSend(
"/sub/chatroom/" + chatroomId, "해당 채팅방은 한 명만 남은 채팅방입니다!", accessor.getMessageHeaders());
private String translationDivide(Chatroom chatroom, String settingLanguage, Member exitMember) {

String baseMessage = "📢 ";
ResourceBundle resourceBundle;
String chatroomName = chatroom.getName();
baseMessage += "(IN CHATROOM, " + chatroomName + ")";
resourceBundle =
ResourceBundle.getBundle("notification.whenGroupChatroomAlone", Locale.getDefault());
String messageSuffix = resourceBundle.getString(settingLanguage.toUpperCase());
baseMessage += messageSuffix;
return baseMessage;
}

public void notificate(Chatroom chatroom, Member exitMember) {

Set<Member> members = chatroom.getMembers();
Member member =
members.stream()
.findFirst()
.orElseThrow(() -> new NoSuchElementException("Member not found"));

String settingLanguage = member.getSettingLanguage();
List<NotificationToken> notificationTokens = member.getNotificationTokens();

String notificationMessage = translationDivide(chatroom, settingLanguage, exitMember);

for (NotificationToken notificationToken : notificationTokens) {
Notification notification = new Notification();
notification.setNotificationToken(notificationToken);
notification.setType(NotificationType.CHATROOM);
notification.setCreated(LocalDateTime.now());
notification.setMessage(notificationMessage);
notificationToken.getNotifications().add(notification);

notificationService.sendPushNotification(
notificationToken.getPushToken(), notification.getCreated(), notificationMessage);
}
}
}
2 changes: 2 additions & 0 deletions src/main/java/com/dife/api/model/Chat.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public class Chat implements TranslateTable {

private LocalDateTime created;

private Boolean isOtherRead = false;

@Override
public String getTextToTranslate() {
return message;
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/dife/api/model/dto/ChatResponseDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ public class ChatResponseDto {

private List<String> imgCode;
private LocalDateTime created;

private Boolean isOtherRead;
}
10 changes: 7 additions & 3 deletions src/main/java/com/dife/api/repository/BookmarkRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@
public interface BookmarkRepository extends JpaRepository<Bookmark, Long> {

@Query(
"SELECT b FROM Bookmark b JOIN b.member m JOIN m.chatrooms c WHERE m = :member AND c.id = :chatroomId")
List<Bookmark> findBookmarksByMemberAndChatroomId(
@Param("chatroomId") Long chatroomId, @Param("member") Member member);
"SELECT b FROM Bookmark b "
+ "JOIN b.member m "
+ "JOIN Chatroom cr ON cr.id = :chatroomId "
+ "JOIN cr.chats c "
+ "WHERE m = :member AND b.message = c.message")
List<Bookmark> findBookmarksByMemberAndChatroom(
@Param("member") Member member, @Param("chatroomId") Long chatroomId);

List<Bookmark> findAllByMember(Member member);

Expand Down
17 changes: 9 additions & 8 deletions src/main/java/com/dife/api/service/BookmarkService.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.dife.api.model.dto.BookmarkResponseDto;
import com.dife.api.repository.*;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
Expand Down Expand Up @@ -53,16 +54,16 @@ public List<BookmarkResponseDto> getChatroomBookmarks(Long chatroomId, String me

Chatroom chatroom =
chatroomRepository.findById(chatroomId).orElseThrow(ChatroomNotFoundException::new);
if (!chatroom.getMembers().contains(member)) {
throw new BookmarkNotFoundException();
}

if (chatroom.getMembers().contains(member)) {
List<Bookmark> bookmarks =
bookmarkRepository.findBookmarksByMemberAndChatroomId(chatroomId, member);
List<Bookmark> bookmarks =
bookmarkRepository.findBookmarksByMemberAndChatroom(member, chatroomId);

return bookmarks.stream()
.map(b -> modelMapper.map(b, BookmarkResponseDto.class))
.collect(toList());
}
throw new BookmarkNotFoundException();
return bookmarks.stream()
.map(b -> modelMapper.map(b, BookmarkResponseDto.class))
.collect(Collectors.toList());
}

public BookmarkResponseDto createBookmark(
Expand Down
39 changes: 28 additions & 11 deletions src/main/java/com/dife/api/service/ChatService.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.dife.api.service;

import static com.dife.api.model.ChatroomType.GROUP;
import static com.dife.api.model.ChatroomType.SINGLE;

import com.dife.api.exception.ChatroomException;
import com.dife.api.exception.ChatroomNotFoundException;
import com.dife.api.exception.MemberNotFoundException;
Expand Down Expand Up @@ -192,35 +195,49 @@ public void exit(ChatRequestDto dto, SimpMessageHeaderAccessor headerAccessor)
chatroomRepository
.findById(dto.getChatroomId())
.orElseThrow(ChatroomNotFoundException::new);
ChatroomSetting setting = chatroom.getChatroomSetting();

Member member = memberService.getMemberEntityById(dto.getMemberId());

if (chatroom.getChatroomType() == SINGLE) {
handleExit(dto, headerAccessor, chatroom, member);
return;
}

ChatroomSetting originalSetting = chatroom.getChatroomSetting();

handleExit(dto, headerAccessor, chatroom, member);

chatroom.setChatroomSetting(originalSetting);
chatroomRepository.save(chatroom);
}

private void handleExit(
ChatRequestDto dto,
SimpMessageHeaderAccessor headerAccessor,
Chatroom chatroom,
Member member)
throws JsonProcessingException {

Long chatroomId = dto.getChatroomId();
String sessionId = headerAccessor.getSessionId();

if (!chatroom.getMembers().contains(member)) {
disconnectHandler.disconnect(chatroom.getId(), sessionId);
disconnectHandler.disconnect(chatroomId, sessionId);
return;
}

String username = (String) headerAccessor.getSessionAttributes().get("username");
dto.setUsername(username);

if (!disconnectHandler.isExitDisconnectChecked(chatroom, sessionId)) return;

chatServiceFacade.decrease(chatroomId);
if (chatroom.getChatroomType() == GROUP) chatServiceFacade.decrease(chatroomId);

chatroom.getMembers().remove(member);
disconnectHandler.disconnect(chatroomId, sessionId);

String exitMessage = username + "님이 퇴장하셨습니다!";
String exitMessage = member.getUsername() + "님이 퇴장하셨습니다!";
Chat chat = saveChat(member, chatroom, exitMessage);

redisPublisher.publish(dealDto(chat, member, chatroom));
notificationHandler.isAlone(chatroom, sessionId);

chatroom.setChatroomSetting(setting);
chatroomRepository.save(chatroom);
notificationHandler.isAlone(chatroom, member);
}

public Chat saveChat(Member member, Chatroom chatroom, String message) {
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/dife/api/service/ChatroomService.java
Original file line number Diff line number Diff line change
Expand Up @@ -387,14 +387,15 @@ public ChatResponseDto getChat(Long chatroomId, Long chatId, String memberEmail)

Chatroom chatroom =
chatroomRepository.findById(chatroomId).orElseThrow(ChatroomNotFoundException::new);

if (!chatroom.getMembers().contains(member)) throw new ChatroomException("소속회원만이 채팅 불러올 수 있음");

Chat chat =
chatRepository
.findByChatroomIdAndId(chatroomId, chatId)
.orElseThrow(ChatNotFoundException::new);

if (!chat.getMember().equals(member) && !chat.getIsOtherRead()) chat.setIsOtherRead(true);

ChatResponseDto responseDto = modelMapper.map(chat, ChatResponseDto.class);

if (chatroom.getChatroomType() == ChatroomType.GROUP)
Expand Down
7 changes: 0 additions & 7 deletions src/main/java/com/dife/api/service/MemberService.java
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,6 @@ public MemberResponseDto getMember(String email) {

Member member = memberRepository.findByEmail(email).orElseThrow(MemberNotFoundException::new);
MemberResponseDto responseDto = memberModelMapper.map(member, MemberResponseDto.class);
if (member.getProfileImg() != null)
responseDto.setProfileImg(modelMapper.map(member.getProfileImg(), File.class));
return responseDto;
}

Expand All @@ -257,9 +255,6 @@ public MemberResponseDto getMemberById(Long id, String memberEmail) {
MemberResponseDto responseDto = memberModelMapper.map(findMember, MemberResponseDto.class);

responseDto.setIsLiked(likeService.isLikeListMember(member, findMember));

if (member.getProfileImg() != null)
responseDto.setProfileImg(modelMapper.map(member.getProfileImg(), File.class));
return responseDto;
}

Expand Down Expand Up @@ -598,8 +593,6 @@ public List<MemberResponseDto> getSearchMembers(String keyword, String memberEma
private MemberResponseDto getMemberResponseDto(Member member, Member currentMember) {
MemberResponseDto responseDto = memberModelMapper.map(member, MemberResponseDto.class);
responseDto.setIsLiked(likeService.isLikeListMember(currentMember, member));
if (member.getProfileImg() != null)
responseDto.setProfileImg(modelMapper.map(member.getProfileImg(), File.class));
return responseDto;
}

Expand Down
12 changes: 12 additions & 0 deletions src/main/resources/db/changelog/v1.0/v1.0.4.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">

<changeSet id="add-type-column-from-chat-20240929-0630" author="suyeon">
<addColumn tableName="chat">
<column name="is_other_read" type="boolean"/>
</addColumn>
</changeSet>
</databaseChangeLog>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
EN = You are the only one left in the chatroom
KO = \uCC44\uD305\uBC29\uC5D0 \uD63C\uC790 \uB0A8\uC558\uC2B5\uB2C8\uB2E4
ZH = \u7684\u804A\u5929\u623F\u95F4\u91CC\u72EC\u81EA\u7559\u4E0B\u4E86
JA = \u3068\u306E\u30C1\u30E3\u30C3\u30C8\u30EB\u30FC\u30E0\u306B\u4E00\u4EBA\u3060\u3051\u6B8B\u3063\u3066\u3044\u307E\u3059
ES = \u00A1Te has quedado solo en la sala de chat con

0 comments on commit 47cc7c9

Please sign in to comment.