-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5e8c9b7
commit 242d651
Showing
12 changed files
with
313 additions
and
14 deletions.
There are no files selected for viewing
13 changes: 13 additions & 0 deletions
13
...p-external-api/src/main/java/kr/co/fitapet/api/common/event/notification/NoticeEvent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package kr.co.fitapet.api.common.event.notification; | ||
|
||
import kr.co.fitapet.infra.client.fcm.NotificationDataKey; | ||
import lombok.Builder; | ||
|
||
import java.util.Map; | ||
|
||
@Builder | ||
public record NoticeEvent( | ||
NoticeType noticeType, | ||
Map<NotificationDataKey, ?> data | ||
) { | ||
} |
26 changes: 26 additions & 0 deletions
26
...nal-api/src/main/java/kr/co/fitapet/api/common/event/notification/NoticeEventHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package kr.co.fitapet.api.common.event.notification; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.context.ApplicationEventPublisher; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.transaction.annotation.Propagation; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import org.springframework.transaction.event.TransactionPhase; | ||
import org.springframework.transaction.event.TransactionalEventListener; | ||
|
||
@Slf4j | ||
@Component | ||
@RequiredArgsConstructor | ||
public class NoticeEventHandler { | ||
private final ApplicationEventPublisher eventPublisher; | ||
|
||
@Transactional(propagation = Propagation.REQUIRES_NEW) | ||
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, fallbackExecution = true) | ||
public void handleNoticeEventToManager(NoticeEvent event) { | ||
log.info("handleNoticeEvent: {}", event); | ||
// notice 저장 | ||
// notice 전송할 대상 조회 (deviceToken 리스트) | ||
// deviceToken 리스트 전체 NotificationEvent 등록 | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
...pp-external-api/src/main/java/kr/co/fitapet/api/common/event/notification/NoticeType.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package kr.co.fitapet.api.common.event.notification; | ||
|
||
import lombok.Getter; | ||
|
||
import java.text.MessageFormat; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
/** | ||
* 알림 타입을 정의하는 클래스입니다. | ||
* | ||
* <p> | ||
* 알림 타입은 [DOMAIN]_[ACTION]_[FROM]_[TO] 혹은 [DOMAIN]_[ACTION]_[FROM]_[SUBJECT] 형식으로 정의합니다. (FROM, TO, SUBJECT는 선택사항입니다.) | ||
* NoticeContentType은 각 알림 타입에 대한 이름, 제목 및 내용을 정의합니다. | ||
* </p> | ||
*/ | ||
@Getter | ||
public enum NoticeType { | ||
/* 공지사항 */ | ||
ANNOUNCEMENT("%s", "%s"), | ||
|
||
/* 케어 */ | ||
CARE_DO_FROM_SUBJECT("케어 완료", "%s님이 %s의 %s 케어를 완료했어요.", "fromName", "subjectName", "domainName"), // from, 반려동물 이름(SUBJECT), 케어이름(DOMAIN) | ||
CARE_CANCEL_FROM_SUBJECT("케어 취소", "%s님이 %s의 %s 케어를 취소했어요.", "fromName", "subjectName", "domainName"), // from, 반려동물 이름(SUBJECT), 케어이름(DOMAIN) | ||
CARE_ALARM_SUBJECT("케어 알림", "%s의 %s 케어가 아직 완료되지 않았어요.", "subjectName", "domainName"), // 반려동물 이름(SUBJECT), 케어이름(DOMAIN) | ||
|
||
/* 멤버 */ | ||
MANAGER_INVITED_FROM_SUBJECT("관리자 초대", "%s님이 %s 관리에 초대했어요.", "fromName", "subjectName"), // from, 반려동물 이름(SUBJECT) | ||
MANAGER_ACCEPT_FROM_SUBJECT("관리자 초대 승인", "%s님이 %s의 케어 멤버 초대를 수락했어요.", "fromName", "subjectName"), // from, 반려동물 이름(SUBJECT) | ||
MANAGER_JOIN_FROM_SUBJECT("관리자 가입", "%s님이 %s의 케어 멤버로 참여했어요.", "fromName", "subjectName"), // from, 반려동물 이름(SUBJECT) | ||
MANAGER_DELEGATE_TO_SUBJECT("관리자 위임", "%s의 관리자가 %s님으로 변경되었어요.", "subjectName", "toName"), // 반려동물 이름(SUBJECT), to | ||
; | ||
|
||
private final String title; | ||
private final String contentFormat; | ||
private final List<String> order; | ||
|
||
NoticeType(String title, String contentFormat, String ...args) { | ||
this.title = title; | ||
this.contentFormat = contentFormat; | ||
this.order = List.of(args); | ||
} | ||
|
||
/** | ||
* 알림 타입에 맞는 내용을 생성합니다. | ||
* @param args Map<String, String> : 알림 타입에 맞는 인자 | ||
* @return String : content | ||
*/ | ||
public String createFormattedContent(Map<String, String> args) { | ||
if (this.name().equals(ANNOUNCEMENT.name())) throw new IllegalStateException("공지사항은 포맷팅할 수 없습니다."); | ||
if (args.size() != order.size()) throw new IllegalArgumentException("포맷팅할 수 없는 인자입니다."); | ||
|
||
Object[] arguments = order.stream().map(args::get).toArray(); | ||
return MessageFormat.format(contentFormat, arguments); | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
fitapet-app-external-api/src/test/java/kr/co/fitapet/common/StringFormatTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package kr.co.fitapet.common; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
public class StringFormatTest { | ||
@Test | ||
public void plainFormatter() { | ||
String format = "안녕하세요, %s님. %s에 오신 것을 환영합니다."; | ||
String name = "홍길동"; | ||
String time = "오늘"; | ||
String result = String.format(format, name, time); | ||
System.out.println(result); | ||
} | ||
|
||
@Test | ||
public void noneMatchingArgument() { | ||
String format = "안녕하세요, %s님. 오신 것을 환영합니다."; | ||
String name = "홍길동"; | ||
String time = "오늘"; | ||
String result = String.format(format, name, time); | ||
System.out.println(result); | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
fitapet-domain/src/main/java/kr/co/fitapet/domain/domains/device/domain/DeviceToken.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package kr.co.fitapet.domain.domains.device.domain; | ||
|
||
import jakarta.persistence.*; | ||
import kr.co.fitapet.domain.domains.member.domain.Member; | ||
import lombok.AccessLevel; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import org.springframework.data.annotation.CreatedDate; | ||
import org.springframework.data.jpa.domain.support.AuditingEntityListener; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
@Entity | ||
@Getter | ||
@Table(name = "device_token") | ||
@EntityListeners(AuditingEntityListener.class) | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
public class DeviceToken { | ||
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
private String deviceToken; | ||
private String os; | ||
private String deviceName; | ||
|
||
@CreatedDate | ||
private LocalDateTime createdAt; | ||
|
||
@JoinColumn(name = "member_id") | ||
@ManyToOne(fetch = FetchType.LAZY) | ||
private Member member; | ||
|
||
private DeviceToken(String deviceToken, String os, String deviceName, Member member) { | ||
this.deviceToken = deviceToken; | ||
this.os = os; | ||
this.deviceName = deviceName; | ||
this.member = member; | ||
} | ||
|
||
public static DeviceToken of(String deviceToken, String os, String deviceName, Member member) { | ||
return new DeviceToken(deviceToken, os, deviceName, member); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
fitapet-infra/src/main/java/kr/co/fitapet/infra/client/fcm/NotificationDataKey.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package kr.co.fitapet.infra.client.fcm; | ||
|
||
import com.fasterxml.jackson.annotation.JsonValue; | ||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
import java.util.List; | ||
|
||
@RequiredArgsConstructor | ||
public enum NotificationDataKey { | ||
NOTICE_TYPE("noticeType"), | ||
FROM_ID("fromId"), | ||
FROM_NAME("fromName"), | ||
TO_ID("toId"), | ||
TO_NAME("toName"), | ||
DOMAIN_ID("domainId"), | ||
DOMAIN_NAME("domainName"), | ||
SUBJECT_ID("subjectId"), | ||
SUBJECT_NAME("subjectName"), | ||
; | ||
private final String field; | ||
|
||
@JsonValue | ||
public String getField() { | ||
return field; | ||
} | ||
|
||
public List<String> getNameFields() { | ||
return List.of("fromName", "toName", "domainName", "subjectName"); | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
fitapet-infra/src/main/java/kr/co/fitapet/infra/client/fcm/NotificationEvent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package kr.co.fitapet.infra.client.fcm; | ||
|
||
import lombok.Builder; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
/** | ||
* FCM Push Notification Event를 위한 Object | ||
* | ||
* <p> | ||
* 하나 이상의 디바이스에 푸시 알림을 보내기 위한 객체입니다. | ||
* 푸시 알림은 단일 디바이스, 여러 디바이스 또는 토픽으로 보낼 수 있습니다. | ||
* 푸시 알림에는 제목, 내용 및 이미지 URL이 포함될 수 있습니다. | ||
* 푸시 알림이 토픽으로 보내지는 경우 deviceTokens 필드는 null이어야 합니다. | ||
* </p> | ||
* @param deviceTokens List<String> : 푸시 알림을 받을 디바이스 토큰 리스트 | ||
* @param title String : 푸시 알림 제목 | ||
* @param topic String : 푸시 알림을 받을 토픽 | ||
* @param content String : 푸시 알림 내용 | ||
* @param imageUrl String : 푸시 알림 이미지 URL | ||
*/ | ||
@Builder | ||
public record NotificationEvent( | ||
List<String> deviceTokens, | ||
String title, | ||
String topic, | ||
String content, | ||
String imageUrl, | ||
Map<String, String> data | ||
) { | ||
public boolean isTopic() { | ||
return this.deviceTokens == null; | ||
} | ||
|
||
public boolean isMulticast() { | ||
return this.deviceTokens() != null && this.deviceTokens().size() > 1; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
...pet-infra/src/main/java/kr/co/fitapet/infra/common/event/FcmNotificationEventHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package kr.co.fitapet.infra.common.event; | ||
|
||
import com.google.firebase.FirebaseException; | ||
import kr.co.fitapet.infra.client.fcm.NotificationEvent; | ||
import kr.co.fitapet.infra.client.fcm.NotificationRequest; | ||
import kr.co.fitapet.infra.client.fcm.NotificationService; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.transaction.event.TransactionalEventListener; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class FcmNotificationEventHandler { | ||
private final NotificationService notificationService; | ||
|
||
@TransactionalEventListener | ||
public void handleTokensEvent(NotificationEvent event) { | ||
log.info("handleTokensEvent: {}", event); | ||
NotificationRequest request = NotificationRequest.fromEvent(event); | ||
|
||
try { | ||
if (event.isTopic()) { | ||
notificationService.sendMessagesToTopic(request); | ||
} else if (event.isMulticast()) { | ||
notificationService.sendMessages(request); | ||
} else { | ||
notificationService.sendMessage(request); | ||
} | ||
} catch (FirebaseException e) { | ||
e.printStackTrace(); | ||
} | ||
|
||
log.info("Successfully sent FCM message"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.