라이브룸 메시지 다국어 처리

This commit is contained in:
2025-12-23 14:20:52 +09:00
parent fd94df338b
commit 39d13ab7c3
7 changed files with 339 additions and 114 deletions

View File

@@ -707,6 +707,177 @@ class SodaMessageSource {
) )
) )
private val liveRoomMessages = mapOf(
"live.room.max_reservations" to mapOf(
Lang.KO to "예약 라이브는 최대 3개까지 가능합니다.",
Lang.EN to "You can reserve up to 3 live sessions.",
Lang.JA to "予約ライブは最大3件まで可能です。"
),
"live.room.cover_image_required" to mapOf(
Lang.KO to "커버이미지를 선택해 주세요.",
Lang.EN to "Please select a cover image.",
Lang.JA to "カバー画像を選択してください。"
),
"live.room.start_time_minimum" to mapOf(
Lang.KO to "현재시각 기준, 30분 이후부터 설정가능합니다.",
Lang.EN to "You can set it from 30 minutes after the current time.",
Lang.JA to "現在時刻から30分後以降に設定できます。"
),
"live.room.password_required" to mapOf(
Lang.KO to "방 입장 비밀번호 6자리를 입력해 주세요.",
Lang.EN to "Please enter a 6-digit room password.",
Lang.JA to "入室パスワード6桁を入力してください。"
),
"live.room.paid_min_can" to mapOf(
Lang.KO to "유료라이브는 10캔부터 설정 가능 합니다.",
Lang.EN to "Paid live can be set from 10 cans.",
Lang.JA to "有料ライブは10缶から設定できます。"
),
"live.room.already_ended" to mapOf(
Lang.KO to "이미 종료된 방입니다.",
Lang.EN to "This room has already ended.",
Lang.JA to "すでに終了したルームです。"
),
"live.room.adult_verification_required" to mapOf(
Lang.KO to "본인인증이 필요한 서비스 입니다.",
Lang.EN to "This service requires identity verification.",
Lang.JA to "本人認証が必要なサービスです。"
),
"live.room.not_found" to mapOf(
Lang.KO to "해당하는 라이브가 없습니다.",
Lang.EN to "Live session not found.",
Lang.JA to "該当するライブがありません。"
),
"live.room.start_available_after" to mapOf(
Lang.KO to "%s 이후에 시작할 수 있습니다.",
Lang.EN to "You can start after %s.",
Lang.JA to "%s以降に開始できます。"
),
"live.room.cancel_reason_required" to mapOf(
Lang.KO to "취소사유를 입력해 주세요.",
Lang.EN to "Please enter a cancellation reason.",
Lang.JA to "キャンセル理由を入力してください。"
),
"live.room.password_mismatch" to mapOf(
Lang.KO to "비밀번호가 일치하지 않습니다.\n다시 확인 후 입력해주세요.",
Lang.EN to "Password does not match.\nPlease check and try again.",
Lang.JA to "パスワードが一致しません。\n確認して入力してください。"
),
"live.room.enter_blocked_by_host" to mapOf(
Lang.KO to "%s님의 요청으로 라이브에 입장할 수 없습니다.",
Lang.EN to "You cannot enter the live at %s's request.",
Lang.JA to "%sの要請によりライブに入場できません。"
),
"live.room.participation_blocked_by_host" to mapOf(
Lang.KO to "%s님의 요청으로 라이브에 참여할 수 없습니다.",
Lang.EN to "You cannot participate in the live at %s's request.",
Lang.JA to "%sの要請によりライブに参加できません。"
),
"live.room.full" to mapOf(
Lang.KO to "방이 가득찼습니다.",
Lang.EN to "The room is full.",
Lang.JA to "ルームが満員です。"
),
"live.room.insufficient_can" to mapOf(
Lang.KO to "%d캔이 부족합니다. 충전 후 이용해 주세요.",
Lang.EN to "You need %d more cans. Please top up and try again.",
Lang.JA to "%d缶が不足しています。チャージしてご利用ください。"
),
"live.room.recent_not_found" to mapOf(
Lang.KO to "최근 데이터가 없습니다.",
Lang.EN to "No recent data found.",
Lang.JA to "最近のデータがありません。"
),
"live.room.no_changes" to mapOf(
Lang.KO to "변경사항이 없습니다.",
Lang.EN to "There are no changes.",
Lang.JA to "変更事項がありません。"
),
"live.room.info_not_found" to mapOf(
Lang.KO to "해당하는 라이브의 정보가 없습니다.",
Lang.EN to "Live session information not found.",
Lang.JA to "該当するライブの情報がありません。"
),
"live.room.speaker_limit_exceeded" to mapOf(
Lang.KO to "스피커 정원이 초과하였습니다.",
Lang.EN to "Speaker capacity exceeded.",
Lang.JA to "スピーカーの定員を超えました。"
),
"live.room.user_not_found" to mapOf(
Lang.KO to "해당하는 유저가 없습니다.",
Lang.EN to "User not found.",
Lang.JA to "該当するユーザーがいません。"
),
"live.room.already_manager" to mapOf(
Lang.KO to "이미 매니저 입니다.",
Lang.EN to "Already a manager.",
Lang.JA to "すでにマネージャーです。"
),
"live.room.creator_contract_only_donation" to mapOf(
Lang.KO to "주식회사 소다라이브와 계약한\n크리에이터에게만 후원을 하실 수 있습니다.",
Lang.EN to "You can only donate to creators contracted with Sodalive Co., Ltd.",
Lang.JA to "株式会社ソダライブと契約した\nクリエイターにのみ支援できます。"
),
"live.room.donation_refund_failed" to mapOf(
Lang.KO to "후원에 실패한 캔이 환불되지 않았습니다\n고객센터로 문의해주세요.",
Lang.EN to "Cans from the failed donation have not been refunded.\nPlease contact customer support.",
Lang.JA to "支援失敗分の缶が返金されていません。\nカスタマーサポートへお問い合わせください。"
),
"live.room.datetime_format" to mapOf(
Lang.KO to "yyyy년 MM월 dd일 (E) a hh시 mm분",
Lang.EN to "yyyy MMM dd (EEE) h:mm a",
Lang.JA to "yyyy年 MM月 dd日 (E) a hh時 mm分"
),
"live.room.datetime_format_detail" to mapOf(
Lang.KO to "yyyy.MM.dd E hh:mm a",
Lang.EN to "yyyy.MM.dd E hh:mm a",
Lang.JA to "yyyy.MM.dd E hh:mm a"
),
"live.room.fcm.message.started" to mapOf(
Lang.KO to "라이브를 시작했습니다. - %s",
Lang.EN to "Live started. - %s",
Lang.JA to "ライブを開始しました。 - %s"
),
"live.room.fcm.message.reserved" to mapOf(
Lang.KO to "라이브를 예약했습니다. - %s",
Lang.EN to "Live reserved. - %s",
Lang.JA to "ライブを予約しました。 - %s"
),
"live.room.fcm.message.started_now" to mapOf(
Lang.KO to "라이브를 시작했습니다 - %s",
Lang.EN to "Live started - %s",
Lang.JA to "ライブを開始しました - %s"
),
"live.room.fcm.message.canceled" to mapOf(
Lang.KO to "라이브 취소 : %s",
Lang.EN to "Live canceled: %s",
Lang.JA to "ライブ取消: %s"
),
"live.room.can_title" to mapOf(
Lang.KO to "%d 캔",
Lang.EN to "%d cans",
Lang.JA to "%d 缶"
),
"live.room.refund_method" to mapOf(
Lang.KO to "환불",
Lang.EN to "Refund",
Lang.JA to "返金"
)
)
private val liveRoomMenuMessages = mapOf(
"live.room.menu.max_count" to mapOf(
Lang.KO to "메뉴판의 최대개수는 3개입니다.",
Lang.EN to "Menu presets are limited to 3.",
Lang.JA to "メニューボードは最大3個までです。"
),
"live.room.menu.blank_not_allowed" to mapOf(
Lang.KO to "메뉴판은 빈칸일 수 없습니다.",
Lang.EN to "Menu cannot be blank.",
Lang.JA to "メニューボードは空欄にできません。"
)
)
private val memberProviderMessages = mapOf( private val memberProviderMessages = mapOf(
"member.provider.email" to mapOf( "member.provider.email" to mapOf(
Lang.KO to "이메일", Lang.KO to "이메일",
@@ -740,6 +911,11 @@ class SodaMessageSource {
Lang.KO to "", Lang.KO to "",
Lang.EN to "Female", Lang.EN to "Female",
Lang.JA to "女性" Lang.JA to "女性"
),
"member.gender.unknown" to mapOf(
Lang.KO to "",
Lang.EN to "Unknown",
Lang.JA to "不明"
) )
) )
@@ -775,6 +951,8 @@ class SodaMessageSource {
memberSocialMessages, memberSocialMessages,
liveRouletteMessages, liveRouletteMessages,
liveTagMessages, liveTagMessages,
liveRoomMessages,
liveRoomMenuMessages,
memberProviderMessages, memberProviderMessages,
memberGenderMessages memberGenderMessages
) )

View File

@@ -56,7 +56,7 @@ class LiveRoomController(
@RequestPart("request") requestString: String, @RequestPart("request") requestString: String,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.createLiveRoom(coverImage, requestString, member)) ApiResponse.ok(service.createLiveRoom(coverImage, requestString, member))
} }
@@ -67,7 +67,7 @@ class LiveRoomController(
@RequestParam timezone: String, @RequestParam timezone: String,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.getRoomDetail(id, member, timezone)) ApiResponse.ok(service.getRoomDetail(id, member, timezone))
} }
@@ -77,7 +77,7 @@ class LiveRoomController(
@RequestBody request: EnterOrQuitLiveRoomRequest, @RequestBody request: EnterOrQuitLiveRoomRequest,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.enterLive(request, member)) ApiResponse.ok(service.enterLive(request, member))
} }
@@ -87,7 +87,7 @@ class LiveRoomController(
@RequestBody request: StartLiveRequest, @RequestBody request: StartLiveRequest,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.startLive(request, member)) ApiResponse.ok(service.startLive(request, member))
} }
@@ -97,7 +97,7 @@ class LiveRoomController(
@RequestBody request: CancelLiveRequest, @RequestBody request: CancelLiveRequest,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.cancelLive(request, member)) ApiResponse.ok(service.cancelLive(request, member))
} }
@@ -106,7 +106,7 @@ class LiveRoomController(
fun getRecentRoomInfo( fun getRecentRoomInfo(
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.getRecentRoomInfo(member)) ApiResponse.ok(service.getRecentRoomInfo(member))
} }
@@ -118,7 +118,7 @@ class LiveRoomController(
@RequestPart("request") requestString: String?, @RequestPart("request") requestString: String?,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.editLiveRoomInfo(roomId, coverImage, requestString, member)) ApiResponse.ok(service.editLiveRoomInfo(roomId, coverImage, requestString, member))
} }
@@ -128,7 +128,7 @@ class LiveRoomController(
@PathVariable id: Long, @PathVariable id: Long,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.getRoomInfo(roomId = id, member)) ApiResponse.ok(service.getRoomInfo(roomId = id, member))
} }
@@ -138,7 +138,7 @@ class LiveRoomController(
@RequestParam roomId: Long, @RequestParam roomId: Long,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.getDonationMessageList(roomId, member)) ApiResponse.ok(service.getDonationMessageList(roomId, member))
} }
@@ -148,7 +148,7 @@ class LiveRoomController(
@RequestBody request: DeleteLiveRoomDonationMessage, @RequestBody request: DeleteLiveRoomDonationMessage,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.deleteDonationMessage(request, member)) ApiResponse.ok(service.deleteDonationMessage(request, member))
} }
@@ -159,7 +159,7 @@ class LiveRoomController(
@PathVariable("user_id") userId: Long, @PathVariable("user_id") userId: Long,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.getUserProfile(roomId, userId, member)) ApiResponse.ok(service.getUserProfile(roomId, userId, member))
} }
@@ -169,7 +169,7 @@ class LiveRoomController(
@PathVariable("id") roomId: Long, @PathVariable("id") roomId: Long,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.getDonationTotal(roomId)) ApiResponse.ok(service.getDonationTotal(roomId))
} }
@@ -179,7 +179,7 @@ class LiveRoomController(
@RequestBody request: SetManagerOrSpeakerOrAudienceRequest, @RequestBody request: SetManagerOrSpeakerOrAudienceRequest,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.setSpeaker(request)) ApiResponse.ok(service.setSpeaker(request))
} }
@@ -189,7 +189,7 @@ class LiveRoomController(
@RequestBody request: SetManagerOrSpeakerOrAudienceRequest, @RequestBody request: SetManagerOrSpeakerOrAudienceRequest,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.setListener(request)) ApiResponse.ok(service.setListener(request))
} }
@@ -199,7 +199,7 @@ class LiveRoomController(
@RequestBody request: SetManagerOrSpeakerOrAudienceRequest, @RequestBody request: SetManagerOrSpeakerOrAudienceRequest,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.setManager(request, member)) ApiResponse.ok(service.setManager(request, member))
} }
@@ -209,7 +209,7 @@ class LiveRoomController(
@RequestBody request: LiveRoomDonationRequest, @RequestBody request: LiveRoomDonationRequest,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.donation(request, member)) ApiResponse.ok(service.donation(request, member))
} }
@@ -219,7 +219,7 @@ class LiveRoomController(
@RequestBody request: LiveRoomDonationRequest, @RequestBody request: LiveRoomDonationRequest,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.donationV2(request, member)) ApiResponse.ok(service.donationV2(request, member))
} }
@@ -229,7 +229,7 @@ class LiveRoomController(
@PathVariable id: Long, @PathVariable id: Long,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.refundDonation(id, member)) ApiResponse.ok(service.refundDonation(id, member))
} }
@@ -239,7 +239,7 @@ class LiveRoomController(
@PathVariable("id") roomId: Long, @PathVariable("id") roomId: Long,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.getDonationStatus(roomId, memberId = member.id!!)) ApiResponse.ok(service.getDonationStatus(roomId, memberId = member.id!!))
} }
@@ -249,7 +249,7 @@ class LiveRoomController(
@RequestParam("id") roomId: Long, @RequestParam("id") roomId: Long,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.quitRoom(roomId, member)) ApiResponse.ok(service.quitRoom(roomId, member))
} }
@@ -257,7 +257,7 @@ class LiveRoomController(
fun recentVisitRoomUsers( fun recentVisitRoomUsers(
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(visitService.getRecentVisitRoomUsers(member)) ApiResponse.ok(visitService.getRecentVisitRoomUsers(member))
} }
@@ -267,7 +267,7 @@ class LiveRoomController(
@RequestBody request: LiveRoomLikeHeartRequest, @RequestBody request: LiveRoomLikeHeartRequest,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.likeHeart(request, member)) ApiResponse.ok(service.likeHeart(request, member))
} }
@@ -277,7 +277,7 @@ class LiveRoomController(
@PathVariable("id") roomId: Long, @PathVariable("id") roomId: Long,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.getTotalHeartCount(roomId)) ApiResponse.ok(service.getTotalHeartCount(roomId))
} }
@@ -287,7 +287,7 @@ class LiveRoomController(
@PathVariable("id") roomId: Long, @PathVariable("id") roomId: Long,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.getHeartList(roomId)) ApiResponse.ok(service.getHeartList(roomId))
} }

View File

@@ -21,6 +21,8 @@ import kr.co.vividnext.sodalive.explorer.ExplorerQueryRepository
import kr.co.vividnext.sodalive.extensions.convertLocalDateTime import kr.co.vividnext.sodalive.extensions.convertLocalDateTime
import kr.co.vividnext.sodalive.fcm.FcmEvent import kr.co.vividnext.sodalive.fcm.FcmEvent
import kr.co.vividnext.sodalive.fcm.FcmEventType import kr.co.vividnext.sodalive.fcm.FcmEventType
import kr.co.vividnext.sodalive.i18n.LangContext
import kr.co.vividnext.sodalive.i18n.SodaMessageSource
import kr.co.vividnext.sodalive.live.reservation.LiveReservationRepository import kr.co.vividnext.sodalive.live.reservation.LiveReservationRepository
import kr.co.vividnext.sodalive.live.room.cancel.CancelLiveRequest import kr.co.vividnext.sodalive.live.room.cancel.CancelLiveRequest
import kr.co.vividnext.sodalive.live.room.cancel.LiveRoomCancel import kr.co.vividnext.sodalive.live.room.cancel.LiveRoomCancel
@@ -68,7 +70,6 @@ import java.time.LocalDateTime
import java.time.ZoneId import java.time.ZoneId
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.util.Date import java.util.Date
import java.util.Locale
import java.util.concurrent.locks.ReentrantReadWriteLock import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.write import kotlin.concurrent.write
@@ -76,6 +77,8 @@ import kotlin.concurrent.write
@Transactional(readOnly = true) @Transactional(readOnly = true)
class LiveRoomService( class LiveRoomService(
private val menuService: LiveRoomMenuService, private val menuService: LiveRoomMenuService,
private val messageSource: SodaMessageSource,
private val langContext: LangContext,
private val repository: LiveRoomRepository, private val repository: LiveRoomRepository,
private val rouletteRepository: NewRouletteRepository, private val rouletteRepository: NewRouletteRepository,
@@ -114,6 +117,15 @@ class LiveRoomService(
) { ) {
private val tokenLocks: MutableMap<Long, ReentrantReadWriteLock> = mutableMapOf() private val tokenLocks: MutableMap<Long, ReentrantReadWriteLock> = mutableMapOf()
private fun formatMessage(key: String, vararg args: Any): String {
val template = messageSource.getMessage(key, langContext.lang).orEmpty()
return if (args.isNotEmpty()) {
String.format(template, *args)
} else {
template
}
}
@Transactional(readOnly = true) @Transactional(readOnly = true)
fun getRoomList( fun getRoomList(
dateString: String?, dateString: String?,
@@ -169,13 +181,16 @@ class LiveRoomService(
} }
} }
val beginDateTimeFormat = messageSource
.getMessage("live.room.datetime_format", langContext.lang)
.orEmpty()
val beginDateTime = it.beginDateTime val beginDateTime = it.beginDateTime
.atZone(ZoneId.of("UTC")) .atZone(ZoneId.of("UTC"))
.withZoneSameInstant(ZoneId.of(timezone)) .withZoneSameInstant(ZoneId.of(timezone))
.format( .format(
DateTimeFormatter DateTimeFormatter
.ofPattern("yyyy년 MM월 dd일 (E) a hh시 mm분") .ofPattern(beginDateTimeFormat)
.withLocale(Locale.KOREAN) .withLocale(langContext.lang.locale)
) )
val beginDateTimeUtc = it.beginDateTime val beginDateTimeUtc = it.beginDateTime
@@ -270,12 +285,12 @@ class LiveRoomService(
@Transactional @Transactional
fun createLiveRoom(coverImage: MultipartFile?, requestString: String, member: Member): CreateLiveRoomResponse { fun createLiveRoom(coverImage: MultipartFile?, requestString: String, member: Member): CreateLiveRoomResponse {
if (repository.getActiveRoomIdList(memberId = member.id!!) >= 3) { if (repository.getActiveRoomIdList(memberId = member.id!!) >= 3) {
throw SodaException("예약 라이브는 최대 3개까지 가능합니다.") throw SodaException(messageKey = "live.room.max_reservations")
} }
val request = objectMapper.readValue(requestString, CreateLiveRoomRequest::class.java) val request = objectMapper.readValue(requestString, CreateLiveRoomRequest::class.java)
if (request.coverImageUrl == null && coverImage == null) { if (request.coverImageUrl == null && coverImage == null) {
throw SodaException("커버이미지를 선택해 주세요.") throw SodaException(messageKey = "live.room.cover_image_required")
} }
val now = LocalDateTime.now() val now = LocalDateTime.now()
@@ -299,18 +314,18 @@ class LiveRoomService(
request.beginDateTimeString != null && request.beginDateTimeString != null &&
beginDateTime < now.plusMinutes(30) beginDateTime < now.plusMinutes(30)
) { ) {
throw SodaException("현재시각 기준, 30분 이후부터 설정가능합니다.") throw SodaException(messageKey = "live.room.start_time_minimum")
} }
if ( if (
request.type == LiveRoomType.PRIVATE && request.type == LiveRoomType.PRIVATE &&
(request.password == null || request.password.length != 6) (request.password == null || request.password.length != 6)
) { ) {
throw SodaException("방 입장 비밀번호 6자리를 입력해 주세요.") throw SodaException(messageKey = "live.room.password_required")
} }
if (request.price in 1..9) { if (request.price in 1..9) {
throw SodaException("유료라이브는 10캔부터 설정 가능 합니다.") throw SodaException(messageKey = "live.room.paid_min_can")
} }
val room = LiveRoom( val room = LiveRoom(
@@ -392,15 +407,17 @@ class LiveRoomService(
} }
} }
val createdMessage = if (createdRoom.channelName != null) {
formatMessage("live.room.fcm.message.started", createdRoom.title)
} else {
formatMessage("live.room.fcm.message.reserved", createdRoom.title)
}
applicationEventPublisher.publishEvent( applicationEventPublisher.publishEvent(
FcmEvent( FcmEvent(
type = FcmEventType.CREATE_LIVE, type = FcmEventType.CREATE_LIVE,
title = createdRoom.member!!.nickname, title = createdRoom.member!!.nickname,
message = if (createdRoom.channelName != null) { message = createdMessage,
"라이브를 시작했습니다. - ${createdRoom.title}"
} else {
"라이브를 예약했습니다. - ${createdRoom.title}"
},
isAuth = createdRoom.isAdult, isAuth = createdRoom.isAdult,
isAvailableJoinCreator = createdRoom.isAvailableJoinCreator, isAvailableJoinCreator = createdRoom.isAvailableJoinCreator,
roomId = createdRoom.id, roomId = createdRoom.id,
@@ -413,11 +430,7 @@ class LiveRoomService(
FcmEvent( FcmEvent(
type = FcmEventType.CREATE_LIVE, type = FcmEventType.CREATE_LIVE,
title = createdRoom.member!!.nickname, title = createdRoom.member!!.nickname,
message = if (createdRoom.channelName != null) { message = createdMessage,
"라이브를 시작했습니다. - ${createdRoom.title}"
} else {
"라이브를 예약했습니다. - ${createdRoom.title}"
},
isAuth = createdRoom.isAdult, isAuth = createdRoom.isAdult,
isAvailableJoinCreator = createdRoom.isAvailableJoinCreator, isAvailableJoinCreator = createdRoom.isAvailableJoinCreator,
roomId = createdRoom.id, roomId = createdRoom.id,
@@ -431,16 +444,23 @@ class LiveRoomService(
fun getRoomDetail(roomId: Long, member: Member, timezone: String): GetRoomDetailResponse { fun getRoomDetail(roomId: Long, member: Member, timezone: String): GetRoomDetailResponse {
val room = repository.getLiveRoom(id = roomId) val room = repository.getLiveRoom(id = roomId)
?: throw SodaException("이미 종료된 방입니다") ?: throw SodaException(messageKey = "live.room.already_ended")
if (room.isAdult && member.auth == null) { if (room.isAdult && member.auth == null) {
throw SodaException("본인인증이 필요한 서비스 입니다.") throw SodaException(messageKey = "live.room.adult_verification_required")
} }
val detailDateTimeFormat = messageSource
.getMessage("live.room.datetime_format_detail", langContext.lang)
.orEmpty()
val beginDateTime = room.beginDateTime val beginDateTime = room.beginDateTime
.atZone(ZoneId.of("UTC")) .atZone(ZoneId.of("UTC"))
.withZoneSameInstant(ZoneId.of(timezone)) .withZoneSameInstant(ZoneId.of(timezone))
.format(DateTimeFormatter.ofPattern("yyyy.MM.dd E hh:mm a")) .format(
DateTimeFormatter
.ofPattern(detailDateTimeFormat)
.withLocale(langContext.lang.locale)
)
val response = GetRoomDetailResponse( val response = GetRoomDetailResponse(
roomId = roomId, roomId = roomId,
@@ -526,18 +546,27 @@ class LiveRoomService(
@Transactional @Transactional
fun startLive(request: StartLiveRequest, member: Member) { fun startLive(request: StartLiveRequest, member: Member) {
val room = repository.getLiveRoomAndAccountId(request.roomId, member.id!!) val room = repository.getLiveRoomAndAccountId(request.roomId, member.id!!)
?: throw SodaException("해당하는 라이브가 없습니다.") ?: throw SodaException(messageKey = "live.room.not_found")
val nowDateTime = LocalDateTime.now() val nowDateTime = LocalDateTime.now()
if (nowDateTime.plusMinutes(10).isBefore(room.beginDateTime)) { if (nowDateTime.plusMinutes(10).isBefore(room.beginDateTime)) {
val startAvailableDateFormat = messageSource
.getMessage("live.room.datetime_format", langContext.lang)
.orEmpty()
val startAvailableDateTimeString = room.beginDateTime val startAvailableDateTimeString = room.beginDateTime
.minusMinutes(10) .minusMinutes(10)
.atZone(ZoneId.of("UTC")) .atZone(ZoneId.of("UTC"))
.withZoneSameInstant(ZoneId.of("Asia/Seoul")) .withZoneSameInstant(ZoneId.of("Asia/Seoul"))
.format(DateTimeFormatter.ofPattern("yyyy년 MM월 dd일 (E) a hh시 mm분").withLocale(Locale.KOREAN)) .format(
DateTimeFormatter
.ofPattern(startAvailableDateFormat)
.withLocale(langContext.lang.locale)
)
throw SodaException("$startAvailableDateTimeString 이후에 시작할 수 있습니다.") throw SodaException(
message = formatMessage("live.room.start_available_after", startAvailableDateTimeString)
)
} }
val activeRooms = repository.getRoomActiveAndChannelNameIsNotNull(memberId = member.id!!) val activeRooms = repository.getRoomActiveAndChannelNameIsNotNull(memberId = member.id!!)
@@ -556,11 +585,12 @@ class LiveRoomService(
room.beginDateTime = nowDateTime room.beginDateTime = nowDateTime
val startedMessage = formatMessage("live.room.fcm.message.started_now", room.title)
applicationEventPublisher.publishEvent( applicationEventPublisher.publishEvent(
FcmEvent( FcmEvent(
type = FcmEventType.START_LIVE, type = FcmEventType.START_LIVE,
title = room.member!!.nickname, title = room.member!!.nickname,
message = "라이브를 시작했습니다 - ${room.title}", message = startedMessage,
isAuth = room.isAdult, isAuth = room.isAdult,
isAvailableJoinCreator = room.isAvailableJoinCreator, isAvailableJoinCreator = room.isAvailableJoinCreator,
roomId = room.id, roomId = room.id,
@@ -573,7 +603,7 @@ class LiveRoomService(
FcmEvent( FcmEvent(
type = FcmEventType.START_LIVE, type = FcmEventType.START_LIVE,
title = room.member!!.nickname, title = room.member!!.nickname,
message = "라이브를 시작했습니다 - ${room.title}", message = startedMessage,
isAuth = room.isAdult, isAuth = room.isAdult,
isAvailableJoinCreator = room.isAvailableJoinCreator, isAvailableJoinCreator = room.isAvailableJoinCreator,
roomId = room.id, roomId = room.id,
@@ -586,10 +616,10 @@ class LiveRoomService(
@Transactional @Transactional
fun cancelLive(request: CancelLiveRequest, member: Member) { fun cancelLive(request: CancelLiveRequest, member: Member) {
val room = repository.getLiveRoomAndAccountId(request.roomId, member.id!!) val room = repository.getLiveRoomAndAccountId(request.roomId, member.id!!)
?: throw SodaException("해당하는 라이브가 없습니다.") ?: throw SodaException(messageKey = "live.room.not_found")
if (request.reason.isBlank()) { if (request.reason.isBlank()) {
throw SodaException("취소사유를 입력해 주세요.") throw SodaException(messageKey = "live.room.cancel_reason_required")
} }
room.isActive = false room.isActive = false
@@ -613,7 +643,7 @@ class LiveRoomService(
it.status = UseCanCalculateStatus.REFUND it.status = UseCanCalculateStatus.REFUND
val charge = Charge(0, it.can, status = ChargeStatus.REFUND_CHARGE) val charge = Charge(0, it.can, status = ChargeStatus.REFUND_CHARGE)
charge.title = "${it.can}" charge.title = formatMessage("live.room.can_title", it.can)
charge.useCan = useCan charge.useCan = useCan
when (it.paymentGateway) { when (it.paymentGateway) {
@@ -627,7 +657,7 @@ class LiveRoomService(
status = PaymentStatus.COMPLETE, status = PaymentStatus.COMPLETE,
paymentGateway = it.paymentGateway paymentGateway = it.paymentGateway
) )
payment.method = "환불" payment.method = formatMessage("live.room.refund_method")
charge.payment = payment charge.payment = payment
chargeRepository.save(charge) chargeRepository.save(charge)
@@ -638,11 +668,12 @@ class LiveRoomService(
val pushTokenListMap = memberRepository.getPushTokenFromReservationList(request.roomId) val pushTokenListMap = memberRepository.getPushTokenFromReservationList(request.roomId)
reservationRepository.cancelReservation(roomId = room.id!!) reservationRepository.cancelReservation(roomId = room.id!!)
val cancelMessage = formatMessage("live.room.fcm.message.canceled", room.title)
applicationEventPublisher.publishEvent( applicationEventPublisher.publishEvent(
FcmEvent( FcmEvent(
type = FcmEventType.CANCEL_LIVE, type = FcmEventType.CANCEL_LIVE,
title = room.member!!.nickname, title = room.member!!.nickname,
message = "라이브 취소 : ${room.title}", message = cancelMessage,
recipientsMap = pushTokenListMap recipientsMap = pushTokenListMap
) )
) )
@@ -651,21 +682,29 @@ class LiveRoomService(
@Transactional @Transactional
fun enterLive(request: EnterOrQuitLiveRoomRequest, member: Member) { fun enterLive(request: EnterOrQuitLiveRoomRequest, member: Member) {
val room = repository.getLiveRoom(id = request.roomId) val room = repository.getLiveRoom(id = request.roomId)
?: throw SodaException("해당하는 라이브가 없습니다.") ?: throw SodaException(messageKey = "live.room.not_found")
if ( if (
room.member!!.id!! != member.id!! && room.member!!.id!! != member.id!! &&
room.type == LiveRoomType.PRIVATE && room.type == LiveRoomType.PRIVATE &&
(request.password == null || request.password != room.password) (request.password == null || request.password != room.password)
) { ) {
throw SodaException("비밀번호가 일치하지 않습니다.\n다시 확인 후 입력해주세요.") throw SodaException(messageKey = "live.room.password_mismatch")
} }
val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = room.member!!.id!!) val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = room.member!!.id!!)
if (isBlocked) throw SodaException("${room.member!!.nickname}님의 요청으로 라이브에 입장할 수 없습니다.") if (isBlocked) {
throw SodaException(
message = formatMessage("live.room.enter_blocked_by_host", room.member!!.nickname)
)
}
val kickOutCount = kickOutService.getKickOutCount(roomId = room.id!!, userId = member.id!!) val kickOutCount = kickOutService.getKickOutCount(roomId = room.id!!, userId = member.id!!)
if (kickOutCount >= 2) throw SodaException("${room.member!!.nickname}님의 요청으로 라이브에 참여할 수 없습니다.") if (kickOutCount >= 2) {
throw SodaException(
message = formatMessage("live.room.participation_blocked_by_host", room.member!!.nickname)
)
}
val lock = getOrCreateLock(memberId = member.id!!) val lock = getOrCreateLock(memberId = member.id!!)
lock.write { lock.write {
@@ -675,7 +714,7 @@ class LiveRoomService(
} }
if (roomInfo.speakerCount + roomInfo.listenerCount + roomInfo.managerCount >= room.numberOfPeople) { if (roomInfo.speakerCount + roomInfo.listenerCount + roomInfo.managerCount >= room.numberOfPeople) {
throw SodaException("방이 가득찼습니다.") throw SodaException(messageKey = "live.room.full")
} }
if ( if (
@@ -684,11 +723,13 @@ class LiveRoomService(
canRepository.isExistPaidLiveRoom(memberId = member.id!!, roomId = request.roomId) == null canRepository.isExistPaidLiveRoom(memberId = member.id!!, roomId = request.roomId) == null
) { ) {
val findMember = memberRepository.findByIdOrNull(id = member.id!!) val findMember = memberRepository.findByIdOrNull(id = member.id!!)
?: throw SodaException("로그인 정보를 확인해 주세요.") ?: throw SodaException(messageKey = "common.error.bad_credentials")
val totalCan = findMember.getChargeCan(request.container) + findMember.getRewardCan(request.container) val totalCan = findMember.getChargeCan(request.container) + findMember.getRewardCan(request.container)
if (totalCan < room.price) { if (totalCan < room.price) {
throw SodaException("${room.price - totalCan}캔이 부족합니다. 충전 후 이용해 주세요.") throw SodaException(
message = formatMessage("live.room.insufficient_can", room.price - totalCan)
)
} }
canPaymentService.spendCan( canPaymentService.spendCan(
@@ -717,18 +758,18 @@ class LiveRoomService(
fun getRecentRoomInfo(member: Member): GetRecentRoomInfoResponse { fun getRecentRoomInfo(member: Member): GetRecentRoomInfoResponse {
return repository.getRecentRoomInfo(memberId = member.id!!) return repository.getRecentRoomInfo(memberId = member.id!!)
?: throw SodaException("최근 데이터가 없습니다.") ?: throw SodaException(messageKey = "live.room.recent_not_found")
} }
@Transactional @Transactional
fun editLiveRoomInfo(roomId: Long, coverImage: MultipartFile?, requestString: String?, member: Member) { fun editLiveRoomInfo(roomId: Long, coverImage: MultipartFile?, requestString: String?, member: Member) {
val room = repository.getLiveRoom(roomId) val room = repository.getLiveRoom(roomId)
if (member.id == null || room?.member?.id != member.id!!) { if (member.id == null || room?.member?.id != member.id!!) {
throw SodaException("잘못된 요청입니다.") throw SodaException(messageKey = "common.error.invalid_request")
} }
if (coverImage == null && requestString == null) { if (coverImage == null && requestString == null) {
throw SodaException("변경사항이 없습니다.") throw SodaException(messageKey = "live.room.no_changes")
} }
if (coverImage != null) { if (coverImage != null) {
@@ -808,10 +849,10 @@ class LiveRoomService(
fun getRoomInfo(roomId: Long, member: Member): GetRoomInfoResponse { fun getRoomInfo(roomId: Long, member: Member): GetRoomInfoResponse {
val roomInfo = roomInfoRepository.findByIdOrNull(roomId) val roomInfo = roomInfoRepository.findByIdOrNull(roomId)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException(messageKey = "live.room.info_not_found")
val room = repository.findByIdOrNull(roomId) val room = repository.findByIdOrNull(roomId)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException(messageKey = "live.room.info_not_found")
val currentTimeStamp = Date().time val currentTimeStamp = Date().time
val expireTimestamp = (currentTimeStamp + (60 * 60 * 24 * 1000)) / 1000 val expireTimestamp = (currentTimeStamp + (60 * 60 * 24 * 1000)) / 1000
@@ -905,10 +946,10 @@ class LiveRoomService(
fun getDonationMessageList(roomId: Long, member: Member): List<LiveRoomDonationMessage> { fun getDonationMessageList(roomId: Long, member: Member): List<LiveRoomDonationMessage> {
val liveRoomCreatorId = repository.getLiveRoomCreatorId(roomId) val liveRoomCreatorId = repository.getLiveRoomCreatorId(roomId)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException(messageKey = "live.room.info_not_found")
val roomInfo = roomInfoRepository.findByIdOrNull(roomId) val roomInfo = roomInfoRepository.findByIdOrNull(roomId)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException(messageKey = "live.room.info_not_found")
return if (liveRoomCreatorId != member.id!!) { return if (liveRoomCreatorId != member.id!!) {
roomInfo.donationMessageList roomInfo.donationMessageList
@@ -922,14 +963,14 @@ class LiveRoomService(
val lock = getOrCreateLock(memberId = member.id!!) val lock = getOrCreateLock(memberId = member.id!!)
lock.write { lock.write {
val room = repository.findByIdOrNull(request.roomId) val room = repository.findByIdOrNull(request.roomId)
?: throw SodaException("해당하는 라이브가 없습니다.") ?: throw SodaException(messageKey = "live.room.not_found")
if (member.id!! != room.member!!.id!!) { if (member.id!! != room.member!!.id!!) {
throw SodaException("잘못된 요청입니다.") throw SodaException(messageKey = "common.error.invalid_request")
} }
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId) val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException(messageKey = "live.room.info_not_found")
roomInfo.removeDonationMessage(request.messageUUID) roomInfo.removeDonationMessage(request.messageUUID)
roomInfoRepository.save(roomInfo) roomInfoRepository.save(roomInfo)
@@ -938,12 +979,12 @@ class LiveRoomService(
fun getUserProfile(roomId: Long, userId: Long, member: Member): GetLiveRoomUserProfileResponse { fun getUserProfile(roomId: Long, userId: Long, member: Member): GetLiveRoomUserProfileResponse {
val room = repository.getLiveRoom(roomId) val room = repository.getLiveRoom(roomId)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException(messageKey = "live.room.info_not_found")
val roomInfo = roomInfoRepository.findByIdOrNull(roomId) val roomInfo = roomInfoRepository.findByIdOrNull(roomId)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException(messageKey = "live.room.info_not_found")
val user = memberRepository.findByIdOrNull(userId) val user = memberRepository.findByIdOrNull(userId)
?: throw SodaException("잘못된 요청입니다.") ?: throw SodaException(messageKey = "common.error.invalid_request")
val isFollowing = if (user.role == MemberRole.CREATOR) { val isFollowing = if (user.role == MemberRole.CREATOR) {
explorerQueryRepository explorerQueryRepository
@@ -981,7 +1022,11 @@ class LiveRoomService(
} else { } else {
"$cloudFrontHost/profile/default-profile.png" "$cloudFrontHost/profile/default-profile.png"
}, },
gender = if (user.gender == Gender.FEMALE) "" else if (user.gender == Gender.MALE) "" else "", gender = when (user.gender) {
Gender.FEMALE -> messageSource.getMessage("member.gender.female", langContext.lang)
Gender.MALE -> messageSource.getMessage("member.gender.male", langContext.lang)
else -> messageSource.getMessage("member.gender.unknown", langContext.lang)
}.orEmpty(),
instagramUrl = user.instagramUrl, instagramUrl = user.instagramUrl,
youtubeUrl = user.youtubeUrl, youtubeUrl = user.youtubeUrl,
websiteUrl = user.websiteUrl, websiteUrl = user.websiteUrl,
@@ -1009,13 +1054,13 @@ class LiveRoomService(
val lock = getOrCreateLock(memberId = request.memberId) val lock = getOrCreateLock(memberId = request.memberId)
lock.write { lock.write {
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId) val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException(messageKey = "live.room.info_not_found")
val member = memberRepository.findByIdOrNull(request.memberId) val member = memberRepository.findByIdOrNull(request.memberId)
?: throw SodaException("로그인 정보를 확인해 주세요.") ?: throw SodaException(messageKey = "common.error.bad_credentials")
if (roomInfo.speakerCount > 5) { if (roomInfo.speakerCount > 5) {
throw SodaException("스피커 정원이 초과하였습니다.") throw SodaException(messageKey = "live.room.speaker_limit_exceeded")
} }
roomInfo.removeListener(member) roomInfo.removeListener(member)
@@ -1030,10 +1075,10 @@ class LiveRoomService(
val lock = getOrCreateLock(memberId = request.memberId) val lock = getOrCreateLock(memberId = request.memberId)
lock.write { lock.write {
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId) val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException(messageKey = "live.room.info_not_found")
val member = memberRepository.findByIdOrNull(request.memberId) val member = memberRepository.findByIdOrNull(request.memberId)
?: throw SodaException("로그인 정보를 확인해 주세요.") ?: throw SodaException(messageKey = "common.error.bad_credentials")
roomInfo.removeSpeaker(member) roomInfo.removeSpeaker(member)
roomInfo.removeManager(member) roomInfo.removeManager(member)
@@ -1046,25 +1091,27 @@ class LiveRoomService(
fun setManager(request: SetManagerOrSpeakerOrAudienceRequest, member: Member) { fun setManager(request: SetManagerOrSpeakerOrAudienceRequest, member: Member) {
val lock = getOrCreateLock(memberId = member.id!!) val lock = getOrCreateLock(memberId = member.id!!)
lock.write { lock.write {
val room = repository.getLiveRoom(request.roomId) ?: throw SodaException("잘못된 요청입니다.") val room = repository.getLiveRoom(request.roomId)
?: throw SodaException(messageKey = "common.error.invalid_request")
if (room.member!!.id!! != member.id!!) { if (room.member!!.id!! != member.id!!) {
throw SodaException("권한이 없습니다.") throw SodaException(messageKey = "common.error.access_denied")
} }
val user = memberRepository.findByIdOrNull(request.memberId) ?: throw SodaException("해당하는 유저가 없습니다.") val user = memberRepository.findByIdOrNull(request.memberId)
?: throw SodaException(messageKey = "live.room.user_not_found")
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId) val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException(messageKey = "live.room.info_not_found")
val roomAccountResponse = LiveRoomMember(member = user, cloudFrontHost) val roomAccountResponse = LiveRoomMember(member = user, cloudFrontHost)
if (roomInfo.managerList.contains(roomAccountResponse)) { if (roomInfo.managerList.contains(roomAccountResponse)) {
throw SodaException("이미 매니저 입니다.") throw SodaException(messageKey = "live.room.already_manager")
} }
if ( if (
!roomInfo.speakerList.contains(roomAccountResponse) && !roomInfo.speakerList.contains(roomAccountResponse) &&
!roomInfo.listenerList.contains(roomAccountResponse) !roomInfo.listenerList.contains(roomAccountResponse)
) { ) {
throw SodaException("해당하는 유저가 없습니다.") throw SodaException(messageKey = "live.room.user_not_found")
} }
roomInfo.removeListener(user) roomInfo.removeListener(user)
@@ -1078,12 +1125,12 @@ class LiveRoomService(
@Transactional @Transactional
fun donation(request: LiveRoomDonationRequest, member: Member): String? { fun donation(request: LiveRoomDonationRequest, member: Member): String? {
val room = repository.findByIdOrNull(request.roomId) val room = repository.findByIdOrNull(request.roomId)
?: throw SodaException("해당하는 라이브가 없습니다.") ?: throw SodaException(messageKey = "live.room.not_found")
val host = room.member ?: throw SodaException("잘못된 요청입니다.") val host = room.member ?: throw SodaException(messageKey = "common.error.invalid_request")
if (host.role != MemberRole.CREATOR) { if (host.role != MemberRole.CREATOR) {
throw SodaException("주식회사 소다라이브와 계약한\n크리에이터에게만 후원을 하실 수 있습니다.") throw SodaException(messageKey = "live.room.creator_contract_only_donation")
} }
canPaymentService.spendCan( canPaymentService.spendCan(
@@ -1099,7 +1146,7 @@ class LiveRoomService(
val lock = getOrCreateLock(memberId = member.id!!) val lock = getOrCreateLock(memberId = member.id!!)
lock.write { lock.write {
val roomInfo = roomInfoRepository.findByIdOrNull(room.id!!) val roomInfo = roomInfoRepository.findByIdOrNull(room.id!!)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException(messageKey = "live.room.info_not_found")
roomInfo.addDonationMessage( roomInfo.addDonationMessage(
memberId = member.id!!, memberId = member.id!!,
@@ -1124,12 +1171,12 @@ class LiveRoomService(
@Transactional @Transactional
fun donationV2(request: LiveRoomDonationRequest, member: Member): LiveRoomDonationResponse? { fun donationV2(request: LiveRoomDonationRequest, member: Member): LiveRoomDonationResponse? {
val room = repository.findByIdOrNull(request.roomId) val room = repository.findByIdOrNull(request.roomId)
?: throw SodaException("해당하는 라이브가 없습니다.") ?: throw SodaException(messageKey = "live.room.not_found")
val host = room.member ?: throw SodaException("잘못된 요청입니다.") val host = room.member ?: throw SodaException(messageKey = "common.error.invalid_request")
if (host.role != MemberRole.CREATOR) { if (host.role != MemberRole.CREATOR) {
throw SodaException("주식회사 소다라이브와 계약한\n크리에이터에게만 후원을 하실 수 있습니다.") throw SodaException(messageKey = "live.room.creator_contract_only_donation")
} }
canPaymentService.spendCan( canPaymentService.spendCan(
@@ -1145,7 +1192,7 @@ class LiveRoomService(
val lock = getOrCreateLock(memberId = member.id!!) val lock = getOrCreateLock(memberId = member.id!!)
lock.write { lock.write {
val roomInfo = roomInfoRepository.findByIdOrNull(room.id!!) val roomInfo = roomInfoRepository.findByIdOrNull(room.id!!)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException(messageKey = "live.room.info_not_found")
roomInfo.addDonationMessage( roomInfo.addDonationMessage(
memberId = member.id!!, memberId = member.id!!,
@@ -1170,20 +1217,20 @@ class LiveRoomService(
@Transactional @Transactional
fun refundDonation(roomId: Long, member: Member) { fun refundDonation(roomId: Long, member: Member) {
val donator = memberRepository.findByIdOrNull(member.id) val donator = memberRepository.findByIdOrNull(member.id)
?: throw SodaException("후원에 실패한 캔이 환불되지 않았습니다\n고객센터로 문의해주세요.") ?: throw SodaException(messageKey = "live.room.donation_refund_failed")
val useCan = canRepository.getCanUsedForLiveRoomNotRefund( val useCan = canRepository.getCanUsedForLiveRoomNotRefund(
memberId = member.id!!, memberId = member.id!!,
roomId = roomId, roomId = roomId,
canUsage = CanUsage.DONATION canUsage = CanUsage.DONATION
) ?: throw SodaException("후원에 실패한 캔이 환불되지 않았습니다\n고객센터로 문의해주세요.") ) ?: throw SodaException(messageKey = "live.room.donation_refund_failed")
useCan.isRefund = true useCan.isRefund = true
val useCanCalculates = useCanCalculateRepository.findByUseCanIdAndStatus(useCan.id!!) val useCanCalculates = useCanCalculateRepository.findByUseCanIdAndStatus(useCan.id!!)
useCanCalculates.forEach { useCanCalculates.forEach {
it.status = UseCanCalculateStatus.REFUND it.status = UseCanCalculateStatus.REFUND
val charge = Charge(0, it.can, status = ChargeStatus.REFUND_CHARGE) val charge = Charge(0, it.can, status = ChargeStatus.REFUND_CHARGE)
charge.title = "${it.can}" charge.title = formatMessage("live.room.can_title", it.can)
charge.useCan = useCan charge.useCan = useCan
when (it.paymentGateway) { when (it.paymentGateway) {
@@ -1197,7 +1244,7 @@ class LiveRoomService(
status = PaymentStatus.COMPLETE, status = PaymentStatus.COMPLETE,
paymentGateway = it.paymentGateway paymentGateway = it.paymentGateway
) )
payment.method = "환불" payment.method = formatMessage("live.room.refund_method")
charge.payment = payment charge.payment = payment
chargeRepository.save(charge) chargeRepository.save(charge)
@@ -1205,7 +1252,7 @@ class LiveRoomService(
} }
fun getDonationStatus(roomId: Long, memberId: Long): GetLiveRoomDonationStatusResponse { fun getDonationStatus(roomId: Long, memberId: Long): GetLiveRoomDonationStatusResponse {
val room = repository.getLiveRoom(roomId) ?: throw SodaException("잘못된 요청입니다.") val room = repository.getLiveRoom(roomId) ?: throw SodaException(messageKey = "common.error.invalid_request")
val isLiveCreator = room.member!!.id == memberId val isLiveCreator = room.member!!.id == memberId
val donationList = repository.getDonationList( val donationList = repository.getDonationList(
@@ -1267,12 +1314,12 @@ class LiveRoomService(
@Transactional @Transactional
fun likeHeart(request: LiveRoomLikeHeartRequest, member: Member) { fun likeHeart(request: LiveRoomLikeHeartRequest, member: Member) {
val room = repository.findByIdOrNull(request.roomId) val room = repository.findByIdOrNull(request.roomId)
?: throw SodaException("해당하는 라이브가 없습니다.") ?: throw SodaException(messageKey = "live.room.not_found")
val host = room.member ?: throw SodaException("잘못된 요청입니다.") val host = room.member ?: throw SodaException(messageKey = "common.error.invalid_request")
if (host.role != MemberRole.CREATOR) { if (host.role != MemberRole.CREATOR) {
throw SodaException("주식회사 소다라이브와 계약한\n크리에이터에게만 후원을 하실 수 있습니다.") throw SodaException(messageKey = "live.room.creator_contract_only_donation")
} }
canPaymentService.spendCan( canPaymentService.spendCan(

View File

@@ -18,7 +18,7 @@ class LiveRoomKickOutController(private val service: LiveRoomKickOutService) {
@RequestBody request: LiveRoomKickOutRequest, @RequestBody request: LiveRoomKickOutRequest,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.kickOut(request = request, member = member)) ApiResponse.ok(service.kickOut(request = request, member = member))
} }

View File

@@ -22,17 +22,17 @@ class LiveRoomKickOutService(
) { ) {
fun kickOut(request: LiveRoomKickOutRequest, member: Member) { fun kickOut(request: LiveRoomKickOutRequest, member: Member) {
val room = roomRepository.findByIdOrNull(request.roomId) val room = roomRepository.findByIdOrNull(request.roomId)
?: throw SodaException("해당하는 라이브가 없습니다.") ?: throw SodaException(messageKey = "live.room.not_found")
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId) val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException(messageKey = "live.room.info_not_found")
if (room.member == null || room.member!!.id == null) { if (room.member == null || room.member!!.id == null) {
throw SodaException("해당하는 라이브가 없습니다.") throw SodaException(messageKey = "live.room.not_found")
} }
if (!roomInfo.managerList.contains(LiveRoomMember(member, cloudFrontHost)) && room.member!!.id != member.id) { if (!roomInfo.managerList.contains(LiveRoomMember(member, cloudFrontHost)) && room.member!!.id != member.id) {
throw SodaException("권한이 없습니다.") throw SodaException(messageKey = "common.error.access_denied")
} }
var liveRoomKickOut = repository.findByIdOrNull(request.roomId) var liveRoomKickOut = repository.findByIdOrNull(request.roomId)

View File

@@ -21,7 +21,7 @@ class LiveRoomMenuController(private val service: LiveRoomMenuService) {
@RequestParam creatorId: Long, @RequestParam creatorId: Long,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok(service.getAllLiveMenu(creatorId = creatorId, memberId = member.id!!)) ApiResponse.ok(service.getAllLiveMenu(creatorId = creatorId, memberId = member.id!!))
} }
@@ -31,7 +31,7 @@ class LiveRoomMenuController(private val service: LiveRoomMenuService) {
@RequestBody request: UpdateLiveMenuRequest, @RequestBody request: UpdateLiveMenuRequest,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
ApiResponse.ok( ApiResponse.ok(
if (request.id > 0) { if (request.id > 0) {

View File

@@ -10,7 +10,7 @@ class LiveRoomMenuService(
private val repository: LiveRoomMenuRepository private val repository: LiveRoomMenuRepository
) { ) {
fun getAllLiveMenu(creatorId: Long, memberId: Long): List<GetMenuPresetResponse> { fun getAllLiveMenu(creatorId: Long, memberId: Long): List<GetMenuPresetResponse> {
if (creatorId != memberId) throw SodaException("잘못된 요청입니다.") if (creatorId != memberId) throw SodaException(messageKey = "common.error.invalid_request")
return repository.findByCreatorId(creatorId) return repository.findByCreatorId(creatorId)
.sortedBy { it.id } .sortedBy { it.id }
@@ -25,7 +25,7 @@ class LiveRoomMenuService(
val menuList = repository.findByCreatorId(creatorId = memberId) val menuList = repository.findByCreatorId(creatorId = memberId)
if (menuList.size >= 3) { if (menuList.size >= 3) {
throw SodaException("메뉴판의 최대개수는 3개입니다.") throw SodaException(messageKey = "live.room.menu.max_count")
} }
if (request.isActive) { if (request.isActive) {
@@ -51,7 +51,7 @@ class LiveRoomMenuService(
val menuList = repository.findByCreatorId(creatorId = memberId) val menuList = repository.findByCreatorId(creatorId = memberId)
if (menuList.isEmpty()) { if (menuList.isEmpty()) {
throw SodaException("잘못된 요청입니다.") throw SodaException(messageKey = "common.error.invalid_request")
} }
menuList.forEach { menuList.forEach {
@@ -95,7 +95,7 @@ class LiveRoomMenuService(
private fun liveMenuValidate(menu: String) { private fun liveMenuValidate(menu: String) {
if (menu.isBlank()) { if (menu.isBlank()) {
throw SodaException("메뉴판은 빈칸일 수 없습니다.") throw SodaException(messageKey = "live.room.menu.blank_not_allowed")
} }
} }