From b04f35c2da8cb4a31514c5c31c7b5c76745c7d73 Mon Sep 17 00:00:00 2001 From: Klaus Date: Wed, 8 Jan 2025 17:38:11 +0900 Subject: [PATCH 1/4] =?UTF-8?q?=EC=98=A4=EB=94=94=EC=85=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20-=20=EC=98=A4=EB=94=94=EC=85=98=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=EB=A5=BC=20=EB=AA=A8=EC=A7=91=EC=A4=91=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=EC=8B=9C=20=EC=98=A4=EB=94=94?= =?UTF-8?q?=EC=85=98=20=EC=95=8C=EB=A6=BC=20=EB=B0=9B=EA=B8=B0=EA=B0=80=20?= =?UTF-8?q?=EB=90=98=EC=96=B4=20=EC=9E=88=EB=8A=94=20=EC=9C=A0=EC=A0=80?= =?UTF-8?q?=EC=97=90=EA=B2=8C=20=ED=91=B8=EC=8B=9C=20=EB=B0=9C=EC=86=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/audition/AdminAuditionService.kt | 16 ++++++++ .../kr/co/vividnext/sodalive/fcm/FcmEvent.kt | 38 ++++++++++++++++++- .../co/vividnext/sodalive/fcm/FcmService.kt | 7 +++- .../sodalive/member/MemberRepository.kt | 32 ++++++++++++++++ .../member/notification/MemberNotification.kt | 5 ++- 5 files changed, 95 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/audition/AdminAuditionService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/audition/AdminAuditionService.kt index b0ad818..6c8663e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/audition/AdminAuditionService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/audition/AdminAuditionService.kt @@ -5,8 +5,11 @@ import kr.co.vividnext.sodalive.admin.audition.role.AdminAuditionRoleRepository import kr.co.vividnext.sodalive.audition.AuditionStatus import kr.co.vividnext.sodalive.aws.s3.S3Uploader import kr.co.vividnext.sodalive.common.SodaException +import kr.co.vividnext.sodalive.fcm.FcmEvent +import kr.co.vividnext.sodalive.fcm.FcmEventType import kr.co.vividnext.sodalive.utils.generateFileName import org.springframework.beans.factory.annotation.Value +import org.springframework.context.ApplicationEventPublisher import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -18,6 +21,7 @@ class AdminAuditionService( private val objectMapper: ObjectMapper, private val repository: AdminAuditionRepository, private val roleRepository: AdminAuditionRoleRepository, + private val applicationEventPublisher: ApplicationEventPublisher, @Value("\${cloud.aws.s3.bucket}") private val bucket: String @@ -82,6 +86,18 @@ class AdminAuditionService( if (request.isActive != null) { audition.isActive = request.isActive } + + if (request.status != null && request.status == AuditionStatus.IN_PROGRESS && audition.isActive) { + applicationEventPublisher.publishEvent( + FcmEvent( + type = FcmEventType.IN_PROGRESS_AUDITION, + title = "새로운 오디션 등록!", + message = "[${audition.title}]이 등록되었습니다. 지금 바로 오리지얼 오디오 드라마 오디션에 지원해보세요!", + isAuth = audition.isAdult, + auditionId = audition.id ?: -1 + ) + ) + } } fun getAuditionList(offset: Long, limit: Long): GetAuditionListResponse { diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmEvent.kt b/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmEvent.kt index 8330a24..6ce30a4 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmEvent.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmEvent.kt @@ -10,7 +10,7 @@ import org.springframework.transaction.event.TransactionalEventListener enum class FcmEventType { ALL, INDIVIDUAL, CREATE_LIVE, START_LIVE, CANCEL_LIVE, UPLOAD_CONTENT, SEND_MESSAGE, CHANGE_NOTICE, - CREATE_CONTENT_COMMENT + CREATE_CONTENT_COMMENT, IN_PROGRESS_AUDITION } class FcmEvent( @@ -25,6 +25,7 @@ class FcmEvent( val contentId: Long? = null, val messageId: Long? = null, val creatorId: Long? = null, + val auditionId: Long? = null, val commentParentId: Long? = null, val myMemberId: Long? = null, val isAvailableJoinCreator: Boolean? = null @@ -278,6 +279,41 @@ class FcmSendListener( } } } + + FcmEventType.IN_PROGRESS_AUDITION -> { + if (fcmEvent.auditionId != null && fcmEvent.auditionId > 0) { + val pushTokenList = memberRepository.getAuditionNoticeRecipientPushTokens( + isAuth = fcmEvent.isAuth ?: false + ) + + val iosPushTokens = pushTokenList["ios"] + val aosPushToken = pushTokenList["aos"] + + if (iosPushTokens != null) { + for (tokens in iosPushTokens) { + pushService.send( + tokens = tokens, + title = fcmEvent.title, + message = fcmEvent.message, + container = "ios", + auditionId = fcmEvent.auditionId + ) + } + } + + if (aosPushToken != null) { + for (tokens in aosPushToken) { + pushService.send( + tokens = tokens, + title = fcmEvent.title, + message = fcmEvent.message, + container = "aos", + auditionId = fcmEvent.auditionId + ) + } + } + } + } } } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmService.kt index f5e8fbf..a0ccd55 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmService.kt @@ -23,7 +23,8 @@ class FcmService { roomId: Long? = null, messageId: Long? = null, contentId: Long? = null, - creatorId: Long? = null + creatorId: Long? = null, + auditionId: Long? = null ) { if (tokens.isNotEmpty()) { logger.info("os: $container") @@ -76,6 +77,10 @@ class FcmService { multicastMessage.putData("channel_id", creatorId.toString()) } + if (auditionId != null) { + multicastMessage.putData("auditionId", auditionId.toString()) + } + val response = FirebaseMessaging.getInstance().sendEachForMulticast(multicastMessage.build()) logger.info("보내기 성공: ${response.successCount}") logger.info("보내기 실패: ${response.failureCount}") diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt index 51f3bd1..9103990 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt @@ -56,6 +56,7 @@ interface MemberQueryRepository { fun getChangeNoticeRecipientPushTokens(creatorId: Long): Map>> fun getPushTokenFromReservationList(roomId: Long): Map>> + fun getAuditionNoticeRecipientPushTokens(isAuth: Boolean): Map>> fun getMemberProfile(memberId: Long, myMemberId: Long): GetMemberProfileResponse } @@ -427,6 +428,37 @@ class MemberQueryRepositoryImpl( return mapOf("aos" to aosPushTokens, "ios" to iosPushTokens) } + override fun getAuditionNoticeRecipientPushTokens(isAuth: Boolean): Map>> { + var where = memberNotification.audition.isTrue + .and(member.pushToken.isNotNull) + + if (isAuth) { + where = where.and(auth.isNotNull) + } + + val aosPushTokens = queryFactory + .select(member.pushToken) + .from(member) + .leftJoin(member.auth, auth) + .leftJoin(memberNotification).on(memberNotification.member.id.eq(member.id)) + .where(where.and(member.container.eq("aos"))) + .fetch() + .toSet() + .chunked(500) + + val iosPushTokens = queryFactory + .select(member.pushToken) + .from(member) + .leftJoin(member.auth, auth) + .leftJoin(memberNotification).on(memberNotification.member.id.eq(member.id)) + .where(where.and(member.container.eq("ios"))) + .fetch() + .toSet() + .chunked(500) + + return mapOf("aos" to aosPushTokens, "ios" to iosPushTokens) + } + override fun getMemberProfile(memberId: Long, myMemberId: Long): GetMemberProfileResponse { return queryFactory .select( diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/notification/MemberNotification.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/notification/MemberNotification.kt index 4c3007a..ab8aed6 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/member/notification/MemberNotification.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/notification/MemberNotification.kt @@ -17,7 +17,10 @@ data class MemberNotification( var live: Boolean? = true, @Column(nullable = false) - var message: Boolean? = true + var message: Boolean? = true, + + @Column(nullable = false) + var audition: Boolean? = false ) : BaseEntity() { @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id", nullable = false) From b4cd489ee9d3c6315c3c723b2f969724188480aa Mon Sep 17 00:00:00 2001 From: Klaus Date: Wed, 8 Jan 2025 17:45:50 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=ED=91=B8=EC=8B=9C=EC=A0=95=EB=B3=B4=20-=20?= =?UTF-8?q?=EC=98=A4=EB=94=94=EC=85=98=20=EC=95=8C=EB=A6=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kr/co/vividnext/sodalive/member/MemberService.kt | 4 +++- .../sodalive/member/info/GetMemberInfoResponse.kt | 3 ++- .../member/notification/MemberNotificationService.kt | 9 ++++++++- .../notification/UpdateNotificationSettingRequest.kt | 1 + 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt index 82896e4..b7fd155 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt @@ -141,7 +141,8 @@ class MemberService( role = member.role, messageNotice = member.notification?.message, followingChannelLiveNotice = member.notification?.live, - followingChannelUploadContentNotice = member.notification?.uploadContent + followingChannelUploadContentNotice = member.notification?.uploadContent, + auditionNotice = member.notification?.audition ) } @@ -151,6 +152,7 @@ class MemberService( live = request.live, uploadContent = request.uploadContent, message = request.message, + audition = request.audition, member = member ) } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/info/GetMemberInfoResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/info/GetMemberInfoResponse.kt index 2db88e6..6d18341 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/member/info/GetMemberInfoResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/info/GetMemberInfoResponse.kt @@ -8,5 +8,6 @@ data class GetMemberInfoResponse( val role: MemberRole, val messageNotice: Boolean?, val followingChannelLiveNotice: Boolean?, - val followingChannelUploadContentNotice: Boolean? + val followingChannelUploadContentNotice: Boolean?, + val auditionNotice: Boolean? ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/notification/MemberNotificationService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/notification/MemberNotificationService.kt index d46fc53..5feee56 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/member/notification/MemberNotificationService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/notification/MemberNotificationService.kt @@ -11,16 +11,23 @@ class MemberNotificationService(private val repository: MemberNotificationReposi live: Boolean? = null, uploadContent: Boolean? = null, message: Boolean? = null, + audition: Boolean? = null, member: Member ) { var notification = repository.getMemberNotification(memberId = member.id!!) if (notification == null) { - notification = MemberNotification(uploadContent, live, message) + notification = MemberNotification( + uploadContent = uploadContent, + live = live, + message = message, + audition = audition + ) notification.member = member repository.save(notification) } else { if (live != null) notification.live = live if (message != null) notification.message = message + if (audition != null) notification.audition = audition if (uploadContent != null) notification.uploadContent = uploadContent } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/notification/UpdateNotificationSettingRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/notification/UpdateNotificationSettingRequest.kt index e9bc210..fbac6eb 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/member/notification/UpdateNotificationSettingRequest.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/notification/UpdateNotificationSettingRequest.kt @@ -3,5 +3,6 @@ package kr.co.vividnext.sodalive.member.notification data class UpdateNotificationSettingRequest( val live: Boolean?, val message: Boolean?, + val audition: Boolean?, val uploadContent: Boolean? ) From 456372c7fb5d706981dc58b69dbbe5e3aecc0cd7 Mon Sep 17 00:00:00 2001 From: Klaus Date: Wed, 8 Jan 2025 18:00:40 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=EC=98=A4=EB=94=94=EC=85=98=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=ED=91=B8=EC=8B=9C=EC=95=8C=EB=A6=BC=20=EB=AC=B8?= =?UTF-8?q?=EA=B5=AC=20=EC=98=A4=ED=83=80=EC=88=98=EC=A0=95=20-=20?= =?UTF-8?q?=EC=98=A4=EB=A6=AC=EC=A7=80=EC=96=BC=20->=20=EC=98=A4=EB=A6=AC?= =?UTF-8?q?=EC=A7=80=EB=84=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vividnext/sodalive/admin/audition/AdminAuditionService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/audition/AdminAuditionService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/audition/AdminAuditionService.kt index 6c8663e..2dc5a2e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/audition/AdminAuditionService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/audition/AdminAuditionService.kt @@ -92,7 +92,7 @@ class AdminAuditionService( FcmEvent( type = FcmEventType.IN_PROGRESS_AUDITION, title = "새로운 오디션 등록!", - message = "[${audition.title}]이 등록되었습니다. 지금 바로 오리지얼 오디오 드라마 오디션에 지원해보세요!", + message = "[${audition.title}]이 등록되었습니다. 지금 바로 오리지널 오디오 드라마 오디션에 지원해보세요!", isAuth = audition.isAdult, auditionId = audition.id ?: -1 ) From dd5e6c399b2a691157b4e10ac562b093ae8be332 Mon Sep 17 00:00:00 2001 From: Klaus Date: Wed, 8 Jan 2025 22:51:48 +0900 Subject: [PATCH 4/4] =?UTF-8?q?=EC=98=A4=EB=94=94=EC=85=98=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=ED=91=B8=EC=8B=9C=EC=95=8C=EB=A6=BC=20-=20data=20k?= =?UTF-8?q?ey=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmService.kt index a0ccd55..3b0a9ab 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/fcm/FcmService.kt @@ -78,7 +78,7 @@ class FcmService { } if (auditionId != null) { - multicastMessage.putData("auditionId", auditionId.toString()) + multicastMessage.putData("audition_id", auditionId.toString()) } val response = FirebaseMessaging.getInstance().sendEachForMulticast(multicastMessage.build())