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..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 @@ -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..3b0a9ab 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("audition_id", 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/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/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) 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? )