Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package org.bookwoori.chat.domain.channelMessage.entity;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.AccessLevel;
Expand All @@ -13,6 +15,7 @@
import org.bookwoori.chat.global.common.EmojiType;
import org.bookwoori.chat.global.common.EventType;
import org.bookwoori.chat.global.common.MessageType;
import org.bookwoori.chat.global.common.dto.MemberProfileDto;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;
Expand Down Expand Up @@ -46,6 +49,16 @@ public class ChannelMessage {
/*
* 데이터베이스에 저장되지 않는 필드
*/

@Transient
private String nickname;

@Transient
private String profileImg;

@Transient
private List<Long> target = new ArrayList<>();

@Transient
private Long parentMemberId;

Expand Down Expand Up @@ -77,6 +90,15 @@ public void modifyContent(String content) {
this.modifiedAt = LocalDateTime.now();
}

public void setProfile(MemberProfileDto profile) {
this.nickname = profile.nickname();
this.profileImg = profile.profileImg();
}

public void setTarget(List<Long> target) {
this.target = target;
}

public void setEventType(EventType eventType) {
this.eventType = eventType;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package org.bookwoori.chat.domain.directMessage.entity;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.AccessLevel;
Expand All @@ -13,6 +15,7 @@
import org.bookwoori.chat.global.common.EmojiType;
import org.bookwoori.chat.global.common.EventType;
import org.bookwoori.chat.global.common.MessageType;
import org.bookwoori.chat.global.common.dto.MemberProfileDto;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;
Expand Down Expand Up @@ -46,6 +49,16 @@ public class DirectMessage {
/*
* 데이터베이스에 저장되지 않는 필드
*/

@Transient
private String nickname;

@Transient
private String profileImg;

@Transient
private List<Long> target = new ArrayList<>();

@Transient
private Long parentMemberId;

Expand Down Expand Up @@ -77,6 +90,15 @@ public void modifyContent(String content) {
this.modifiedAt = LocalDateTime.now();
}

public void setProfile(MemberProfileDto profile) {
this.nickname = profile.nickname();
this.profileImg = profile.profileImg();
}

public void setTarget(List<Long> target) {
this.target = target;
}

public void setEventType(EventType eventType) {
this.eventType = eventType;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.bookwoori.chat.global.common.dto;

public record MemberProfileDto(
String nickname,
String profileImg
) {

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
package org.bookwoori.chat.global.feignClient;

import java.util.Map;
import org.bookwoori.chat.global.common.dto.MemberProfileDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(name = "core", url = "${client.url.core}")
public interface CoreClient {

@GetMapping("/messageRooms/{messageRoomId}/members")
Map<Long, MemberProfileDto> getParticipantsByMessageRoom(
@PathVariable("messageRoomId") Long messageRoomId);

@GetMapping("/channels/{channelId}/members")
Map<Long, MemberProfileDto> getParticipantsByChannel(
@PathVariable("channelId") Long channelId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.bookwoori.chat.global.feignClient;

import org.bookwoori.chat.global.feignClient.dto.MessageNotificationRequestDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;

@FeignClient(name = "noti", url = "${client.url.notification}")
public interface NotificationClient {

@PostMapping("notification-server/direct")
void sendDirectNotification(MessageNotificationRequestDto requestDto);

@PostMapping("notification-server/chat")
void sendChannelNotification(MessageNotificationRequestDto requestDto);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.bookwoori.chat.global.feignClient.dto;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import org.bookwoori.chat.domain.channelMessage.entity.ChannelMessage;
import org.bookwoori.chat.domain.directMessage.entity.DirectMessage;

@Builder
public record MessageNotificationRequestDto(
@NotNull
Long memberId,
@NotNull
String nickname,
@NotNull
String type,
@NotNull
String content,
@JsonInclude(Include.NON_NULL)
Long roomId,
@JsonInclude(Include.NON_NULL)
Long channelId,
@NotNull
String target
) {

public static MessageNotificationRequestDto from(DirectMessage directMessage) {
return MessageNotificationRequestDto.builder()
.memberId(directMessage.getMemberId())
.nickname(directMessage.getNickname())
.type("directMessage")
.content(directMessage.getContent())
.roomId(directMessage.getMessageRoomId())
.target(directMessage.getTarget().toString())
.build();
}

public static MessageNotificationRequestDto from(ChannelMessage channelMessage) {
return MessageNotificationRequestDto.builder()
.memberId(channelMessage.getMemberId())
.nickname(channelMessage.getNickname())
.type("channelMessage")
.content(channelMessage.getContent())
.channelId(channelMessage.getChannelId())
.target(channelMessage.getTarget().toString())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package org.bookwoori.chat.global.kafka;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.bookwoori.chat.domain.channelMessage.dto.request.ChannelMessageDeleteRequestDto;
Expand All @@ -19,8 +22,12 @@
import org.bookwoori.chat.global.common.ActionType;
import org.bookwoori.chat.global.common.EventType;
import org.bookwoori.chat.global.common.MessageType;
import org.bookwoori.chat.global.common.dto.MemberProfileDto;
import org.bookwoori.chat.global.exception.CustomException;
import org.bookwoori.chat.global.exception.ErrorCode;
import org.bookwoori.chat.global.feignClient.CoreClient;
import org.bookwoori.chat.global.feignClient.NotificationClient;
import org.bookwoori.chat.global.feignClient.dto.MessageNotificationRequestDto;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;

Expand All @@ -32,10 +39,35 @@ public class MessageSender { //토픽에 이벤트를 발행
private final KafkaTemplate<String, Object> kafkaTemplate;
private final DirectMessageRepository directMessageRepository;
private final ChannelMessageRepository channelMessageRepository;
private final CoreClient coreClient;
private final NotificationClient notificationClient;

public void sendDirectMessage(DirectMessageSendRequestDto requestDto, Long memberId) {
DirectMessage directMessage = requestDto.toEntity(memberId);
directMessageRepository.save(directMessage);

try {
//알림 전송에 필요한 데이터 구성
Map<Long, MemberProfileDto> participants = coreClient.getParticipantsByMessageRoom(
requestDto.messageRoomId());
List<Long> target = new ArrayList<>();
for (Long key : participants.keySet()) {
if (key.equals(memberId)) {
continue;
}
target.add(key);
}
directMessage.setProfile(participants.get(directMessage.getMemberId()));
directMessage.setTarget(target);

//알림 전송
notificationClient.sendDirectNotification(
MessageNotificationRequestDto.from(directMessage));
} catch (Exception e) {
log.error("Direct Message notification send Failed: {}", directMessage.getId());
log.error(e.getMessage());
}

kafkaTemplate.send(KafkaConstants.DIRECT_CHAT_TOPIC, directMessage);
}

Expand Down Expand Up @@ -98,6 +130,28 @@ public void deleteDirectMessage(DirectMessageDeleteRequestDto requestDto, Long m
public void sendChannelMessage(ChannelMessageSendRequestDto requestDto, Long memberId) {
ChannelMessage channelMessage = requestDto.toEntity(memberId);
channelMessageRepository.save(channelMessage);

try {
//알림 전송에 필요한 데이터 구성
Map<Long, MemberProfileDto> participants = coreClient.getParticipantsByChannel(
requestDto.channelId());
List<Long> target = new ArrayList<>();
for (Long key : participants.keySet()) {
if (key.equals(memberId)) {
continue;
}
target.add(key);
}
channelMessage.setProfile(participants.get(channelMessage.getMemberId()));
channelMessage.setTarget(target);
//알림 전송
notificationClient.sendChannelNotification(
MessageNotificationRequestDto.from(channelMessage));
} catch (Exception e) {
log.error("Channel Message notification send Failed: {}", channelMessage.getId());
log.error(e.getMessage());
}

kafkaTemplate.send(KafkaConstants.CHANNEL_CHAT_TOPIC, channelMessage);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand Down Expand Up @@ -46,4 +47,10 @@ public ResponseEntity<?> updateChannelName(@PathVariable final Long channelId,
channelFacade.modifyChannel(channelId, requestDto);
return ResponseEntity.ok().build();
}

//@Operation(summary = "(채팅) 채널 참여자 정보 조회", description = "(채팅) 채널에 참여하고 있는 회원들의 정보를 조회합니다.")
@GetMapping("/{channelId}/members")
public ResponseEntity<?> getParticipants(@PathVariable final Long channelId) {
return ResponseEntity.ok(channelFacade.getParticipants(channelId));
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package org.bookwoori.core.domain.channel.facade;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.bookwoori.core.domain.category.entity.Category;
import org.bookwoori.core.domain.category.service.CategoryService;
import org.bookwoori.core.domain.channel.dto.request.ChannelCreateRequestDto;
import org.bookwoori.core.domain.channel.dto.request.ChannelModifyRequestDto;
import org.bookwoori.core.domain.channel.entity.Channel;
import org.bookwoori.core.domain.channel.service.ChannelService;
import org.bookwoori.core.domain.member.dto.response.MemberProfileResponseDto;
import org.bookwoori.core.domain.member.entity.Member;
import org.bookwoori.core.domain.server.entity.Server;
import org.bookwoori.core.domain.serverMember.service.ServerMemberService;
import org.bookwoori.core.global.exception.CustomException;
import org.bookwoori.core.global.exception.ErrorCode;
import org.springframework.stereotype.Component;
Expand All @@ -18,6 +25,7 @@ public class ChannelFacade {

private final ChannelService channelService;
private final CategoryService categoryService;
private final ServerMemberService serverMemberService;

@Transactional
public void createChannel(ChannelCreateRequestDto requestDto) {
Expand Down Expand Up @@ -54,4 +62,18 @@ public void deleteChannel(Long channelId) {
channelService.detach(channel);
channelService.deleteChannel(channel);
}

@Transactional(readOnly = true)
public Map<Long, MemberProfileResponseDto> getParticipants(Long channelId) {
Server server = channelService.getChannelById(channelId).getCategory().getServer();
return createProfileMap(serverMemberService.getMembersByServer(server));
}

private Map<Long, MemberProfileResponseDto> createProfileMap(List<Member> members) {
Map<Long, MemberProfileResponseDto> map = new HashMap<>();
for (Member member : members) {
map.put(member.getMemberId(), MemberProfileResponseDto.from(member));
}
return map;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.bookwoori.core.domain.messageRoom.facade.MessageRoomFacade;
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.RequestMapping;
Expand Down Expand Up @@ -36,4 +37,10 @@ public ResponseEntity<?> getMyMessageRoomList(@RequestParam(defaultValue = "0")
return ResponseEntity.ok(messageRoomFacade.getMyMessageRoomList(page, size));
}

//@Operation(summary = "DM 방 참여자 정보 조회", description = "DM 방에 참여하고 있는 회원들의 정보를 조회합니다.")
@GetMapping("/{messageRoomId}/members")
public ResponseEntity<?> getParticipants(@PathVariable final Long messageRoomId) {
return ResponseEntity.ok(messageRoomFacade.getParticipants(messageRoomId));
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.bookwoori.core.domain.messageRoom.facade;

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -85,4 +86,18 @@ public MessageRoomListResponseDto getMyMessageRoomList(int page, int size) {
return new MessageRoomListResponseDto(messageRoomItems);
}

@Transactional(readOnly = true)
public Map<Long, MemberProfileResponseDto> getParticipants(Long messageRoomId) {
MessageRoom messageRoom = messageRoomService.getMessageRoomById(messageRoomId);
return createProfileMap(messageRoom.getSender(), messageRoom.getReceiver());
}

private Map<Long, MemberProfileResponseDto> createProfileMap(Member... members) {
Map<Long, MemberProfileResponseDto> map = new HashMap<>();
for (Member member : members) {
map.put(member.getMemberId(), MemberProfileResponseDto.from(member));
}
return map;
}

}
Loading