feat(chat): 이미지 메시지 조회 시 CloudFront 서명 URL 적용 및 DTO 변환 로직 공통화
- 조회 가능한(보유/무료/결제완료) 이미지 메시지의 이미지 URL을 ImageContentCloudFront.generateSignedURL(만료 5분)로 생성 - 접근 불가(미보유, 유료 미구매) 이미지 메시지는 기존 공개 호스트 URL(블러/스냅샷 경로) 유지 - ChatRoomService에 ImageContentCloudFront를 주입하고, toChatMessageItemDto에서 이미지 URL/hasAccess 결정 로직 단일화 - enterChatRoom, getChatMessages, sendMessage 경로의 중복된 DTO 매핑 로직 제거 - purchaseMessage 결제 완료 시 forceHasAccess=true로 접근 가능 DTO 반환
This commit is contained in:
parent
12574dbe46
commit
5a58fe9077
|
@ -48,6 +48,7 @@ class ChatRoomService(
|
|||
private val characterService: ChatCharacterService,
|
||||
private val characterImageService: CharacterImageService,
|
||||
private val canPaymentService: kr.co.vividnext.sodalive.can.payment.CanPaymentService,
|
||||
private val imageCloudFront: kr.co.vividnext.sodalive.aws.cloudfront.ImageContentCloudFront,
|
||||
|
||||
@Value("\${weraser.api-key}")
|
||||
private val apiKey: String,
|
||||
|
@ -332,40 +333,7 @@ class ChatRoomService(
|
|||
}
|
||||
|
||||
val messagesAsc = fetched.sortedBy { it.createdAt }
|
||||
val items = messagesAsc.map { msg ->
|
||||
val sender = msg.participant
|
||||
val profilePath = when (sender.participantType) {
|
||||
ParticipantType.USER -> sender.member?.profileImage
|
||||
ParticipantType.CHARACTER -> sender.character?.imagePath
|
||||
}
|
||||
val senderImageUrl = "$imageHost/${profilePath ?: "profile/default-profile.png"}"
|
||||
val createdAtMillis = msg.createdAt?.atZone(ZoneId.systemDefault())?.toInstant()?.toEpochMilli()
|
||||
?: 0L
|
||||
ChatMessageItemDto(
|
||||
messageId = msg.id!!,
|
||||
message = msg.message,
|
||||
profileImageUrl = senderImageUrl,
|
||||
mine = sender.member?.id == member.id,
|
||||
createdAt = createdAtMillis,
|
||||
messageType = msg.messageType.name,
|
||||
imageUrl = msg.imagePath?.let { "$imageHost/$it" },
|
||||
price = msg.price,
|
||||
hasAccess = if (msg.messageType == ChatMessageType.IMAGE) {
|
||||
if (msg.price == null) {
|
||||
true
|
||||
} else {
|
||||
msg.characterImage?.id?.let {
|
||||
characterImageService.isOwnedImageByMember(
|
||||
it,
|
||||
member.id!!
|
||||
)
|
||||
} ?: true
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
)
|
||||
}
|
||||
val items = messagesAsc.map { toChatMessageItemDto(it, member) }
|
||||
|
||||
return ChatRoomEnterResponse(
|
||||
roomId = room.id!!,
|
||||
|
@ -512,40 +480,7 @@ class ChatRoomService(
|
|||
// createdAt 오름차순으로 정렬하여 반환
|
||||
val messagesAsc = fetched.sortedBy { it.createdAt }
|
||||
|
||||
val items = messagesAsc.map { msg ->
|
||||
val sender = msg.participant
|
||||
val profilePath = when (sender.participantType) {
|
||||
ParticipantType.USER -> sender.member?.profileImage
|
||||
ParticipantType.CHARACTER -> sender.character?.imagePath
|
||||
}
|
||||
val senderImageUrl = "$imageHost/${profilePath ?: "profile/default-profile.png"}"
|
||||
val createdAtMillis = msg.createdAt?.atZone(ZoneId.systemDefault())?.toInstant()?.toEpochMilli()
|
||||
?: 0L
|
||||
ChatMessageItemDto(
|
||||
messageId = msg.id!!,
|
||||
message = msg.message,
|
||||
profileImageUrl = senderImageUrl,
|
||||
mine = sender.member?.id == member.id,
|
||||
createdAt = createdAtMillis,
|
||||
messageType = msg.messageType.name,
|
||||
imageUrl = msg.imagePath?.let { "$imageHost/$it" },
|
||||
price = msg.price,
|
||||
hasAccess = if (msg.messageType == ChatMessageType.IMAGE) {
|
||||
if (msg.price == null) {
|
||||
true
|
||||
} else {
|
||||
msg.characterImage?.id?.let {
|
||||
characterImageService.isOwnedImageByMember(
|
||||
it,
|
||||
member.id!!
|
||||
)
|
||||
} ?: true
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
)
|
||||
}
|
||||
val items = messagesAsc.map { toChatMessageItemDto(it, member) }
|
||||
|
||||
return ChatMessagesPageResponse(
|
||||
messages = items,
|
||||
|
@ -643,19 +578,7 @@ class ChatRoomService(
|
|||
)
|
||||
)
|
||||
|
||||
val imageDto = ChatMessageItemDto(
|
||||
messageId = imageMsg.id!!,
|
||||
message = imageMsg.message,
|
||||
profileImageUrl = senderImageUrl,
|
||||
mine = false,
|
||||
createdAt = imageMsg.createdAt?.atZone(ZoneId.systemDefault())?.toInstant()
|
||||
?.toEpochMilli()
|
||||
?: 0L,
|
||||
messageType = ChatMessageType.IMAGE.name,
|
||||
imageUrl = imageMsg.imagePath?.let { "$imageHost/$it" },
|
||||
price = imageMsg.price,
|
||||
hasAccess = owned || imageMsg.price == null
|
||||
)
|
||||
val imageDto = toChatMessageItemDto(imageMsg, member)
|
||||
return listOf(textDto, imageDto)
|
||||
}
|
||||
|
||||
|
@ -687,6 +610,23 @@ class ChatRoomService(
|
|||
} else {
|
||||
true
|
||||
}
|
||||
val expirationMs = 5L * 60L * 1000L
|
||||
val resolvedImageUrl: String? = if (msg.messageType == ChatMessageType.IMAGE) {
|
||||
val path = if (hasAccess) {
|
||||
msg.characterImage?.imagePath ?: msg.imagePath
|
||||
} else {
|
||||
msg.imagePath
|
||||
}
|
||||
path?.let { p ->
|
||||
if (hasAccess) {
|
||||
imageCloudFront.generateSignedURL(p, expirationMs)
|
||||
} else {
|
||||
"$imageHost/$p"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
return ChatMessageItemDto(
|
||||
messageId = msg.id!!,
|
||||
message = msg.message,
|
||||
|
@ -694,7 +634,7 @@ class ChatRoomService(
|
|||
mine = sender.member?.id == member.id,
|
||||
createdAt = createdAtMillis,
|
||||
messageType = msg.messageType.name,
|
||||
imageUrl = msg.imagePath?.let { "$imageHost/$it" },
|
||||
imageUrl = resolvedImageUrl,
|
||||
price = msg.price,
|
||||
hasAccess = hasAccess
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue