Compare commits
2 Commits
3cac42b5b9
...
5a56990d0b
Author | SHA1 | Date |
---|---|---|
|
5a56990d0b | |
|
7671e24470 |
|
@ -223,10 +223,9 @@ class LiveRoomController(private val service: LiveRoomService) {
|
||||||
|
|
||||||
@PostMapping("/quit")
|
@PostMapping("/quit")
|
||||||
fun quitRoom(
|
fun quitRoom(
|
||||||
@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("로그인 정보를 확인해주세요.")
|
||||||
ApiResponse.ok(service.quitRoom(roomId, member))
|
ApiResponse.ok(service.quitRoom(member))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,8 @@ 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.concurrent.locks.ReentrantReadWriteLock
|
||||||
|
import kotlin.concurrent.write
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
|
@ -88,6 +90,8 @@ class LiveRoomService(
|
||||||
@Value("\${cloud.aws.cloud-front.host}")
|
@Value("\${cloud.aws.cloud-front.host}")
|
||||||
private val cloudFrontHost: String
|
private val cloudFrontHost: String
|
||||||
) {
|
) {
|
||||||
|
private val tokenLocks: MutableMap<Long, ReentrantReadWriteLock> = mutableMapOf()
|
||||||
|
|
||||||
fun getRoomList(
|
fun getRoomList(
|
||||||
dateString: String?,
|
dateString: String?,
|
||||||
status: LiveRoomStatus,
|
status: LiveRoomStatus,
|
||||||
|
@ -415,49 +419,52 @@ class LiveRoomService(
|
||||||
throw SodaException("비밀번호가 일치하지 않습니다.\n다시 확인 후 입력해주세요.")
|
throw SodaException("비밀번호가 일치하지 않습니다.\n다시 확인 후 입력해주세요.")
|
||||||
}
|
}
|
||||||
|
|
||||||
var roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
|
val lock = getOrCreateLock(memberId = member.id!!)
|
||||||
if (roomInfo == null) {
|
lock.write {
|
||||||
roomInfo = roomInfoRepository.save(LiveRoomInfo(roomId = request.roomId))
|
var roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
|
||||||
}
|
if (roomInfo == null) {
|
||||||
|
roomInfo = roomInfoRepository.save(LiveRoomInfo(roomId = request.roomId))
|
||||||
if (roomInfo.speakerCount + roomInfo.listenerCount + roomInfo.managerCount >= room.numberOfPeople) {
|
|
||||||
throw SodaException("방이 가득찼습니다.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
room.price > 0 &&
|
|
||||||
room.member!!.id!! != member.id!! &&
|
|
||||||
canRepository.isExistPaidLiveRoom(memberId = member.id!!, roomId = request.roomId) == null
|
|
||||||
) {
|
|
||||||
val findMember = memberRepository.findByIdOrNull(id = member.id!!)
|
|
||||||
?: throw SodaException("로그인 정보를 확인해 주세요.")
|
|
||||||
|
|
||||||
val totalCan = findMember.getChargeCan(request.container) + findMember.getRewardCan(request.container)
|
|
||||||
if (totalCan < room.price) {
|
|
||||||
throw SodaException("${room.price - totalCan}캔이 부족합니다. 충전 후 이용해 주세요.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
canPaymentService.spendCan(
|
if (roomInfo.speakerCount + roomInfo.listenerCount + roomInfo.managerCount >= room.numberOfPeople) {
|
||||||
memberId = member.id!!,
|
throw SodaException("방이 가득찼습니다.")
|
||||||
needCan = room.price,
|
}
|
||||||
canUsage = CanUsage.LIVE,
|
|
||||||
liveRoom = room,
|
if (
|
||||||
container = request.container
|
room.price > 0 &&
|
||||||
)
|
room.member!!.id!! != member.id!! &&
|
||||||
|
canRepository.isExistPaidLiveRoom(memberId = member.id!!, roomId = request.roomId) == null
|
||||||
|
) {
|
||||||
|
val findMember = memberRepository.findByIdOrNull(id = member.id!!)
|
||||||
|
?: throw SodaException("로그인 정보를 확인해 주세요.")
|
||||||
|
|
||||||
|
val totalCan = findMember.getChargeCan(request.container) + findMember.getRewardCan(request.container)
|
||||||
|
if (totalCan < room.price) {
|
||||||
|
throw SodaException("${room.price - totalCan}캔이 부족합니다. 충전 후 이용해 주세요.")
|
||||||
|
}
|
||||||
|
|
||||||
|
canPaymentService.spendCan(
|
||||||
|
memberId = member.id!!,
|
||||||
|
needCan = room.price,
|
||||||
|
canUsage = CanUsage.LIVE,
|
||||||
|
liveRoom = room,
|
||||||
|
container = request.container
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
roomInfo.removeListener(member)
|
||||||
|
roomInfo.removeSpeaker(member)
|
||||||
|
roomInfo.removeManager(member)
|
||||||
|
|
||||||
|
if (room.member!!.id == member.id) {
|
||||||
|
roomInfo.addSpeaker(member, cloudFrontHost)
|
||||||
|
} else {
|
||||||
|
roomInfo.addListener(member, cloudFrontHost)
|
||||||
|
}
|
||||||
|
|
||||||
|
roomInfoRepository.save(roomInfo)
|
||||||
|
roomVisitService.roomVisit(room, member)
|
||||||
}
|
}
|
||||||
|
|
||||||
roomInfo.removeListener(member)
|
|
||||||
roomInfo.removeSpeaker(member)
|
|
||||||
roomInfo.removeManager(member)
|
|
||||||
|
|
||||||
if (room.member!!.id == member.id) {
|
|
||||||
roomInfo.addSpeaker(member, cloudFrontHost)
|
|
||||||
} else {
|
|
||||||
roomInfo.addListener(member, cloudFrontHost)
|
|
||||||
}
|
|
||||||
|
|
||||||
roomInfoRepository.save(roomInfo)
|
|
||||||
roomVisitService.roomVisit(room, member)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getRecentRoomInfo(member: Member): GetRecentRoomInfoResponse {
|
fun getRecentRoomInfo(member: Member): GetRecentRoomInfoResponse {
|
||||||
|
@ -621,18 +628,21 @@ class LiveRoomService(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteDonationMessage(request: DeleteLiveRoomDonationMessage, member: Member) {
|
fun deleteDonationMessage(request: DeleteLiveRoomDonationMessage, member: Member) {
|
||||||
val room = repository.findByIdOrNull(request.roomId)
|
val lock = getOrCreateLock(memberId = member.id!!)
|
||||||
?: throw SodaException("해당하는 라이브가 없습니다.")
|
lock.write {
|
||||||
|
val room = repository.findByIdOrNull(request.roomId)
|
||||||
|
?: throw SodaException("해당하는 라이브가 없습니다.")
|
||||||
|
|
||||||
if (member.id!! != room.member!!.id!!) {
|
if (member.id!! != room.member!!.id!!) {
|
||||||
throw SodaException("잘못된 요청입니다.")
|
throw SodaException("잘못된 요청입니다.")
|
||||||
|
}
|
||||||
|
|
||||||
|
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
|
||||||
|
?: throw SodaException("해당하는 라이브의 정보가 없습니다.")
|
||||||
|
|
||||||
|
roomInfo.removeDonationMessage(request.messageUUID)
|
||||||
|
roomInfoRepository.save(roomInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
|
|
||||||
?: throw SodaException("해당하는 라이브의 정보가 없습니다.")
|
|
||||||
|
|
||||||
roomInfo.removeDonationMessage(request.messageUUID)
|
|
||||||
roomInfoRepository.save(roomInfo)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getUserProfile(roomId: Long, userId: Long, member: Member): GetLiveRoomUserProfileResponse {
|
fun getUserProfile(roomId: Long, userId: Long, member: Member): GetLiveRoomUserProfileResponse {
|
||||||
|
@ -701,64 +711,73 @@ class LiveRoomService(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSpeaker(request: SetManagerOrSpeakerOrAudienceRequest) {
|
fun setSpeaker(request: SetManagerOrSpeakerOrAudienceRequest) {
|
||||||
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
|
val lock = getOrCreateLock(memberId = request.memberId)
|
||||||
?: throw SodaException("해당하는 라이브의 정보가 없습니다.")
|
lock.write {
|
||||||
|
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
|
||||||
|
?: throw SodaException("해당하는 라이브의 정보가 없습니다.")
|
||||||
|
|
||||||
val account = memberRepository.findByIdOrNull(request.accountId)
|
val member = memberRepository.findByIdOrNull(request.memberId)
|
||||||
?: throw SodaException("로그인 정보를 확인해 주세요.")
|
?: throw SodaException("로그인 정보를 확인해 주세요.")
|
||||||
|
|
||||||
if (roomInfo.speakerCount > 9) {
|
if (roomInfo.speakerCount > 9) {
|
||||||
throw SodaException("스피커 정원이 초과하였습니다.")
|
throw SodaException("스피커 정원이 초과하였습니다.")
|
||||||
|
}
|
||||||
|
|
||||||
|
roomInfo.removeListener(member)
|
||||||
|
roomInfo.removeManager(member)
|
||||||
|
roomInfo.addSpeaker(member, cloudFrontHost)
|
||||||
|
|
||||||
|
roomInfoRepository.save(roomInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
roomInfo.removeListener(account)
|
|
||||||
roomInfo.removeManager(account)
|
|
||||||
roomInfo.addSpeaker(account, cloudFrontHost)
|
|
||||||
|
|
||||||
roomInfoRepository.save(roomInfo)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setListener(request: SetManagerOrSpeakerOrAudienceRequest) {
|
fun setListener(request: SetManagerOrSpeakerOrAudienceRequest) {
|
||||||
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
|
val lock = getOrCreateLock(memberId = request.memberId)
|
||||||
?: throw SodaException("해당하는 라이브의 정보가 없습니다.")
|
lock.write {
|
||||||
|
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
|
||||||
|
?: throw SodaException("해당하는 라이브의 정보가 없습니다.")
|
||||||
|
|
||||||
val member = memberRepository.findByIdOrNull(request.accountId)
|
val member = memberRepository.findByIdOrNull(request.memberId)
|
||||||
?: throw SodaException("로그인 정보를 확인해 주세요.")
|
?: throw SodaException("로그인 정보를 확인해 주세요.")
|
||||||
|
|
||||||
roomInfo.removeSpeaker(member)
|
roomInfo.removeSpeaker(member)
|
||||||
roomInfo.removeManager(member)
|
roomInfo.removeManager(member)
|
||||||
roomInfo.addListener(member, cloudFrontHost)
|
roomInfo.addListener(member, cloudFrontHost)
|
||||||
|
|
||||||
roomInfoRepository.save(roomInfo)
|
roomInfoRepository.save(roomInfo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setManager(request: SetManagerOrSpeakerOrAudienceRequest, member: Member) {
|
fun setManager(request: SetManagerOrSpeakerOrAudienceRequest, member: Member) {
|
||||||
val room = repository.getLiveRoom(request.roomId) ?: throw SodaException("잘못된 요청입니다.")
|
val lock = getOrCreateLock(memberId = member.id!!)
|
||||||
if (room.member!!.id!! != member.id!!) {
|
lock.write {
|
||||||
throw SodaException("권한이 없습니다.")
|
val room = repository.getLiveRoom(request.roomId) ?: throw SodaException("잘못된 요청입니다.")
|
||||||
|
if (room.member!!.id!! != member.id!!) {
|
||||||
|
throw SodaException("권한이 없습니다.")
|
||||||
|
}
|
||||||
|
|
||||||
|
val user = memberRepository.findByIdOrNull(request.memberId) ?: throw SodaException("해당하는 유저가 없습니다.")
|
||||||
|
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
|
||||||
|
?: throw SodaException("해당하는 라이브의 정보가 없습니다.")
|
||||||
|
|
||||||
|
val roomAccountResponse = LiveRoomMember(member = user, cloudFrontHost)
|
||||||
|
if (roomInfo.managerList.contains(roomAccountResponse)) {
|
||||||
|
throw SodaException("이미 매니저 입니다.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!roomInfo.speakerList.contains(roomAccountResponse) &&
|
||||||
|
!roomInfo.listenerList.contains(roomAccountResponse)
|
||||||
|
) {
|
||||||
|
throw SodaException("해당하는 유저가 없습니다.")
|
||||||
|
}
|
||||||
|
|
||||||
|
roomInfo.removeListener(user)
|
||||||
|
roomInfo.removeSpeaker(user)
|
||||||
|
roomInfo.addManager(user, cloudFrontHost)
|
||||||
|
|
||||||
|
roomInfoRepository.save(roomInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
val user = memberRepository.findByIdOrNull(request.accountId) ?: throw SodaException("해당하는 유저가 없습니다.")
|
|
||||||
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
|
|
||||||
?: throw SodaException("해당하는 라이브의 정보가 없습니다.")
|
|
||||||
|
|
||||||
val roomAccountResponse = LiveRoomMember(member = user, cloudFrontHost)
|
|
||||||
if (roomInfo.managerList.contains(roomAccountResponse)) {
|
|
||||||
throw SodaException("이미 매니저 입니다.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
!roomInfo.speakerList.contains(roomAccountResponse) &&
|
|
||||||
!roomInfo.listenerList.contains(roomAccountResponse)
|
|
||||||
) {
|
|
||||||
throw SodaException("해당하는 유저가 없습니다.")
|
|
||||||
}
|
|
||||||
|
|
||||||
roomInfo.removeListener(user)
|
|
||||||
roomInfo.removeSpeaker(user)
|
|
||||||
roomInfo.addManager(user, cloudFrontHost)
|
|
||||||
|
|
||||||
roomInfoRepository.save(roomInfo)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@ -781,16 +800,19 @@ class LiveRoomService(
|
||||||
)
|
)
|
||||||
|
|
||||||
if (request.message.isNotBlank()) {
|
if (request.message.isNotBlank()) {
|
||||||
val roomInfo = roomInfoRepository.findByIdOrNull(room.id!!)
|
val lock = getOrCreateLock(memberId = member.id!!)
|
||||||
?: throw SodaException("해당하는 라이브의 정보가 없습니다.")
|
lock.write {
|
||||||
|
val roomInfo = roomInfoRepository.findByIdOrNull(room.id!!)
|
||||||
|
?: throw SodaException("해당하는 라이브의 정보가 없습니다.")
|
||||||
|
|
||||||
roomInfo.addDonationMessage(
|
roomInfo.addDonationMessage(
|
||||||
nickname = member.nickname,
|
nickname = member.nickname,
|
||||||
can = request.can,
|
can = request.can,
|
||||||
donationMessage = request.message
|
donationMessage = request.message
|
||||||
)
|
)
|
||||||
|
|
||||||
roomInfoRepository.save(roomInfo)
|
roomInfoRepository.save(roomInfo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -843,20 +865,32 @@ class LiveRoomService(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun quitRoom(roomId: Long, member: Member) {
|
fun quitRoom(member: Member) {
|
||||||
val room = repository.getLiveRoom(roomId)
|
val roomVisit = roomVisitService.getLatestRoomVisit(member.id!!)
|
||||||
val roomInfo = roomInfoRepository.findByIdOrNull(roomId)
|
|
||||||
if (roomInfo != null) {
|
val roomId = roomVisit?.room?.id
|
||||||
if (room?.member != null && room.member!! == member) {
|
if (roomId != null) {
|
||||||
room.isActive = false
|
val lock = getOrCreateLock(memberId = member.id!!)
|
||||||
kickOutService.deleteKickOutData(roomId = room.id!!)
|
lock.write {
|
||||||
roomInfoRepository.deleteById(roomInfo.roomId)
|
val roomInfo = roomInfoRepository.findByIdOrNull(roomId)
|
||||||
} else {
|
if (roomInfo != null) {
|
||||||
roomInfo.removeSpeaker(member)
|
val room = repository.getLiveRoom(roomId) ?: return
|
||||||
roomInfo.removeListener(member)
|
if (room.member != null && room.member!! == member) {
|
||||||
roomInfo.removeManager(member)
|
room.isActive = false
|
||||||
roomInfoRepository.save(roomInfo)
|
kickOutService.deleteKickOutData(roomId = room.id!!)
|
||||||
|
roomInfoRepository.deleteById(roomInfo.roomId)
|
||||||
|
} else {
|
||||||
|
roomInfo.removeSpeaker(member)
|
||||||
|
roomInfo.removeListener(member)
|
||||||
|
roomInfo.removeManager(member)
|
||||||
|
roomInfoRepository.save(roomInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getOrCreateLock(memberId: Long): ReentrantReadWriteLock {
|
||||||
|
return tokenLocks.computeIfAbsent(memberId) { ReentrantReadWriteLock() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,5 +2,5 @@ package kr.co.vividnext.sodalive.live.room
|
||||||
|
|
||||||
data class SetManagerOrSpeakerOrAudienceRequest(
|
data class SetManagerOrSpeakerOrAudienceRequest(
|
||||||
val roomId: Long,
|
val roomId: Long,
|
||||||
val accountId: Long
|
val memberId: Long
|
||||||
)
|
)
|
||||||
|
|
|
@ -13,6 +13,7 @@ interface LiveRoomVisitRepository : JpaRepository<LiveRoomVisit, Long>, LiveRoom
|
||||||
interface LiveRoomVisitQueryRepository {
|
interface LiveRoomVisitQueryRepository {
|
||||||
fun findByRoomIdAndMemberId(roomId: Long, memberId: Long): LiveRoomVisit?
|
fun findByRoomIdAndMemberId(roomId: Long, memberId: Long): LiveRoomVisit?
|
||||||
fun findFirstByMemberIdOrderByUpdatedAtDesc(memberId: Long): LiveRoomVisit?
|
fun findFirstByMemberIdOrderByUpdatedAtDesc(memberId: Long): LiveRoomVisit?
|
||||||
|
fun getLatestRoomVisit(memberId: Long): LiveRoomVisit?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
|
@ -38,4 +39,13 @@ class LiveRoomVisitQueryRepositoryImpl(private val queryFactory: JPAQueryFactory
|
||||||
.orderBy(liveRoomVisit.updatedAt.desc())
|
.orderBy(liveRoomVisit.updatedAt.desc())
|
||||||
.fetchFirst()
|
.fetchFirst()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getLatestRoomVisit(memberId: Long): LiveRoomVisit? {
|
||||||
|
return queryFactory
|
||||||
|
.selectFrom(liveRoomVisit)
|
||||||
|
.innerJoin(liveRoomVisit.member, member)
|
||||||
|
.where(member.id.eq(memberId))
|
||||||
|
.orderBy(liveRoomVisit.updatedAt.desc())
|
||||||
|
.fetchFirst()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,4 +22,8 @@ class LiveRoomVisitService(private val repository: LiveRoomVisitRepository) {
|
||||||
|
|
||||||
repository.save(roomVisit)
|
repository.save(roomVisit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getLatestRoomVisit(memberId: Long): LiveRoomVisit? {
|
||||||
|
return repository.getLatestRoomVisit(memberId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue