182 lines
7.4 KiB
Kotlin
182 lines
7.4 KiB
Kotlin
package kr.co.vividnext.sodalive.fcm
|
|
|
|
import kr.co.vividnext.sodalive.content.comment.AudioContentCommentRepository
|
|
import kr.co.vividnext.sodalive.i18n.Lang
|
|
import kr.co.vividnext.sodalive.i18n.SodaMessageSource
|
|
import kr.co.vividnext.sodalive.live.room.GenderRestriction
|
|
import kr.co.vividnext.sodalive.member.MemberRepository
|
|
import org.springframework.scheduling.annotation.Async
|
|
import org.springframework.stereotype.Component
|
|
import org.springframework.transaction.annotation.Propagation
|
|
import org.springframework.transaction.annotation.Transactional
|
|
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, IN_PROGRESS_AUDITION
|
|
}
|
|
|
|
class FcmEvent(
|
|
val type: FcmEventType,
|
|
val title: String = "",
|
|
val message: String = "",
|
|
val titleKey: String? = null,
|
|
val messageKey: String? = null,
|
|
val args: List<Any> = listOf(),
|
|
val container: String = "",
|
|
val recipients: List<Long> = listOf(),
|
|
val pushTokens: List<PushTokenInfo>? = null,
|
|
val isAuth: Boolean? = null,
|
|
val roomId: Long? = null,
|
|
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,
|
|
val genderRestriction: GenderRestriction? = null
|
|
)
|
|
|
|
@Component
|
|
class FcmSendListener(
|
|
private val pushService: FcmService,
|
|
private val memberRepository: MemberRepository,
|
|
private val contentCommentRepository: AudioContentCommentRepository,
|
|
private val messageSource: SodaMessageSource
|
|
) {
|
|
@Async
|
|
@TransactionalEventListener
|
|
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
|
fun send(fcmEvent: FcmEvent) {
|
|
when (fcmEvent.type) {
|
|
FcmEventType.ALL -> {
|
|
val pushTokens = memberRepository.getAllRecipientPushTokens(
|
|
fcmEvent.isAuth
|
|
)
|
|
sendPush(pushTokens, fcmEvent)
|
|
}
|
|
|
|
FcmEventType.INDIVIDUAL -> {
|
|
if (fcmEvent.recipients.isNotEmpty()) {
|
|
val pushTokens = memberRepository.getIndividualRecipientPushTokens(
|
|
recipients = fcmEvent.recipients,
|
|
isAuth = fcmEvent.isAuth
|
|
)
|
|
sendPush(pushTokens, fcmEvent)
|
|
}
|
|
}
|
|
|
|
FcmEventType.CREATE_LIVE -> {
|
|
val pushTokens = memberRepository.getCreateLiveRoomNotificationRecipientPushTokens(
|
|
creatorId = fcmEvent.creatorId!!,
|
|
isAuth = fcmEvent.isAuth ?: false,
|
|
isAvailableJoinCreator = fcmEvent.isAvailableJoinCreator ?: false,
|
|
genderRestriction = fcmEvent.genderRestriction
|
|
)
|
|
sendPush(pushTokens, fcmEvent, roomId = fcmEvent.roomId)
|
|
}
|
|
|
|
FcmEventType.START_LIVE -> {
|
|
val pushTokens = memberRepository.getStartLiveRoomNotificationRecipientPushTokens(
|
|
creatorId = fcmEvent.creatorId!!,
|
|
roomId = fcmEvent.roomId!!,
|
|
isAuth = fcmEvent.isAuth ?: false,
|
|
isAvailableJoinCreator = fcmEvent.isAvailableJoinCreator ?: false,
|
|
genderRestriction = fcmEvent.genderRestriction
|
|
)
|
|
sendPush(pushTokens, fcmEvent, roomId = fcmEvent.roomId)
|
|
}
|
|
|
|
FcmEventType.CANCEL_LIVE -> {
|
|
if (fcmEvent.pushTokens != null) {
|
|
sendPush(fcmEvent.pushTokens, fcmEvent)
|
|
}
|
|
}
|
|
|
|
FcmEventType.UPLOAD_CONTENT -> {
|
|
val pushTokens = memberRepository.getUploadContentNotificationRecipientPushTokens(
|
|
creatorId = fcmEvent.creatorId!!,
|
|
isAuth = fcmEvent.isAuth ?: false
|
|
)
|
|
sendPush(pushTokens, fcmEvent, contentId = fcmEvent.contentId)
|
|
}
|
|
|
|
FcmEventType.SEND_MESSAGE -> {
|
|
val pushToken = memberRepository.getMessageRecipientPushToken(messageId = fcmEvent.messageId!!)
|
|
if (pushToken != null) {
|
|
sendPush(listOf(pushToken), fcmEvent, messageId = fcmEvent.messageId)
|
|
}
|
|
}
|
|
|
|
FcmEventType.CHANGE_NOTICE -> {
|
|
if (fcmEvent.creatorId != null) {
|
|
val pushTokens = memberRepository.getChangeNoticeRecipientPushTokens(fcmEvent.creatorId)
|
|
sendPush(pushTokens, fcmEvent, creatorId = fcmEvent.creatorId)
|
|
}
|
|
}
|
|
|
|
FcmEventType.CREATE_CONTENT_COMMENT -> {
|
|
if (fcmEvent.myMemberId != null && fcmEvent.contentId != null) {
|
|
val pushTokens = contentCommentRepository.findPushTokenByContentIdAndCommentParentIdMyMemberId(
|
|
contentId = fcmEvent.contentId,
|
|
commentParentId = fcmEvent.commentParentId,
|
|
myMemberId = fcmEvent.myMemberId
|
|
)
|
|
sendPush(pushTokens, fcmEvent, contentId = fcmEvent.contentId)
|
|
}
|
|
}
|
|
|
|
FcmEventType.IN_PROGRESS_AUDITION -> {
|
|
if (fcmEvent.auditionId != null && fcmEvent.auditionId > 0) {
|
|
val pushTokens = memberRepository.getAuditionNoticeRecipientPushTokens(
|
|
isAuth = fcmEvent.isAuth ?: false
|
|
)
|
|
sendPush(pushTokens, fcmEvent, auditionId = fcmEvent.auditionId)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun sendPush(
|
|
pushTokens: List<PushTokenInfo>,
|
|
fcmEvent: FcmEvent,
|
|
roomId: Long? = null,
|
|
contentId: Long? = null,
|
|
messageId: Long? = null,
|
|
creatorId: Long? = null,
|
|
auditionId: Long? = null
|
|
) {
|
|
val tokensByLang = pushTokens.groupBy { it.languageCode }
|
|
|
|
for ((langCode, tokens) in tokensByLang) {
|
|
val lang = Lang.fromAcceptLanguage(langCode)
|
|
val title = translate(fcmEvent.titleKey, fcmEvent.title, lang, fcmEvent.args)
|
|
val message = translate(fcmEvent.messageKey, fcmEvent.message, lang, fcmEvent.args)
|
|
|
|
val tokensByOS = tokens.groupBy { it.deviceType }
|
|
for ((os, osTokens) in tokensByOS) {
|
|
osTokens.map { it.token }.distinct().chunked(500).forEach { batch ->
|
|
pushService.send(
|
|
tokens = batch,
|
|
title = title,
|
|
message = message,
|
|
container = os,
|
|
roomId = roomId ?: fcmEvent.roomId,
|
|
contentId = contentId ?: fcmEvent.contentId,
|
|
messageId = messageId ?: fcmEvent.messageId,
|
|
creatorId = creatorId ?: fcmEvent.creatorId,
|
|
auditionId = auditionId ?: fcmEvent.auditionId
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun translate(key: String?, default: String, lang: Lang, args: List<Any>): String {
|
|
if (key == null) return default
|
|
val template = messageSource.getMessage(key, lang) ?: return default
|
|
return String.format(template, *args.toTypedArray())
|
|
}
|
|
}
|