Compare commits

..

3 Commits

Author SHA1 Message Date
Klaus ae04b22b2a 라이브 만들기, 수정
- 메뉴판 만들기, 수정 기능 추가
2024-03-06 01:40:25 +09:00
Klaus 31e33d49df 라이브 메뉴판
- 불필요한 API 제거
2024-03-06 00:55:37 +09:00
Klaus 59a035e5c2 라이브 정보 조회 API
- 응답에 메뉴판 정보 추가
2024-03-05 22:20:40 +09:00
6 changed files with 100 additions and 74 deletions

View File

@ -11,5 +11,8 @@ data class CreateLiveRoomRequest(
val price: Int = 0, val price: Int = 0,
val timezone: String, val timezone: String,
val type: LiveRoomType = LiveRoomType.OPEN, val type: LiveRoomType = LiveRoomType.OPEN,
val password: String? = null val password: String? = null,
val menuPanId: Long = 0,
val menuPan: String = "",
val isActiveMenuPan: Boolean = false
) )

View File

@ -5,5 +5,8 @@ data class EditLiveRoomInfoRequest(
val notice: String?, val notice: String?,
val numberOfPeople: Int?, val numberOfPeople: Int?,
val beginDateTimeString: String?, val beginDateTimeString: String?,
val timezone: String? val timezone: String?,
val menuPanId: Long = 0,
val menuPan: String = "",
val isActiveMenuPan: Boolean
) )

View File

@ -38,6 +38,9 @@ import kr.co.vividnext.sodalive.live.room.info.LiveRoomInfo
import kr.co.vividnext.sodalive.live.room.info.LiveRoomInfoRedisRepository import kr.co.vividnext.sodalive.live.room.info.LiveRoomInfoRedisRepository
import kr.co.vividnext.sodalive.live.room.info.LiveRoomMember import kr.co.vividnext.sodalive.live.room.info.LiveRoomMember
import kr.co.vividnext.sodalive.live.room.kickout.LiveRoomKickOutService import kr.co.vividnext.sodalive.live.room.kickout.LiveRoomKickOutService
import kr.co.vividnext.sodalive.live.room.menu.CreateLiveMenuRequest
import kr.co.vividnext.sodalive.live.room.menu.LiveRoomMenuService
import kr.co.vividnext.sodalive.live.room.menu.UpdateLiveMenuRequest
import kr.co.vividnext.sodalive.live.room.visit.LiveRoomVisitService import kr.co.vividnext.sodalive.live.room.visit.LiveRoomVisitService
import kr.co.vividnext.sodalive.live.roulette.NewRouletteRepository import kr.co.vividnext.sodalive.live.roulette.NewRouletteRepository
import kr.co.vividnext.sodalive.live.tag.LiveTagRepository import kr.co.vividnext.sodalive.live.tag.LiveTagRepository
@ -65,6 +68,8 @@ import kotlin.concurrent.write
@Service @Service
@Transactional(readOnly = true) @Transactional(readOnly = true)
class LiveRoomService( class LiveRoomService(
private val menuService: LiveRoomMenuService,
private val repository: LiveRoomRepository, private val repository: LiveRoomRepository,
private val rouletteRepository: NewRouletteRepository, private val rouletteRepository: NewRouletteRepository,
private val roomInfoRepository: LiveRoomInfoRedisRepository, private val roomInfoRepository: LiveRoomInfoRedisRepository,
@ -269,6 +274,27 @@ class LiveRoomService(
room.bgImage = request.coverImageUrl room.bgImage = request.coverImageUrl
} }
if (request.isActiveMenuPan) {
if (request.menuPanId > 0) {
menuService.updateLiveMenu(
memberId = member.id!!,
request = UpdateLiveMenuRequest(
id = request.menuPanId,
menu = request.menuPan,
isActive = true
)
)
} else {
menuService.createLiveMenu(
memberId = member.id!!,
request = CreateLiveMenuRequest(
menu = request.menuPan,
isActive = true
)
)
}
}
applicationEventPublisher.publishEvent( applicationEventPublisher.publishEvent(
FcmEvent( FcmEvent(
type = FcmEventType.CREATE_LIVE, type = FcmEventType.CREATE_LIVE,
@ -604,6 +630,28 @@ class LiveRoomService(
throw SodaException("변경사항이 없습니다.") throw SodaException("변경사항이 없습니다.")
} }
if (coverImage != null) {
val metadata = ObjectMetadata()
metadata.contentLength = coverImage.size
// 커버 이미지 파일명 생성
val coverImageFileName = generateFileName(prefix = "${room.id}-cover")
// 커버 이미지 업로드
val coverImagePath = s3Uploader.upload(
inputStream = coverImage.inputStream,
bucket = coverImageBucket,
filePath = "live_room_cover/${room.id}/$coverImageFileName",
metadata = metadata
)
room.bgImage = coverImagePath
if (room.channelName == null) {
room.coverImage = coverImagePath
}
}
if (requestString != null) { if (requestString != null) {
val request = objectMapper.readValue(requestString, EditLiveRoomInfoRequest::class.java) val request = objectMapper.readValue(requestString, EditLiveRoomInfoRequest::class.java)
@ -625,27 +673,28 @@ class LiveRoomService(
.withZoneSameInstant(ZoneId.of("UTC")) .withZoneSameInstant(ZoneId.of("UTC"))
.toLocalDateTime() .toLocalDateTime()
} }
}
if (coverImage != null) { if (request.isActiveMenuPan) {
val metadata = ObjectMetadata() if (request.menuPanId > 0) {
metadata.contentLength = coverImage.size menuService.updateLiveMenu(
memberId = member.id!!,
// 커버 이미지 파일명 생성 request = UpdateLiveMenuRequest(
val coverImageFileName = generateFileName(prefix = "${room.id}-cover") id = request.menuPanId,
menu = request.menuPan,
// 커버 이미지 업로드 isActive = true
val coverImagePath = s3Uploader.upload(
inputStream = coverImage.inputStream,
bucket = coverImageBucket,
filePath = "live_room_cover/${room.id}/$coverImageFileName",
metadata = metadata
) )
)
room.bgImage = coverImagePath } else {
menuService.createLiveMenu(
if (room.channelName == null) { memberId = member.id!!,
room.coverImage = coverImagePath request = CreateLiveMenuRequest(
menu = request.menuPan,
isActive = true
)
)
}
} else {
menuService.deactivateAll(memberId = member.id!!)
} }
} }
} }
@ -703,6 +752,8 @@ class LiveRoomService(
listOf() listOf()
} }
val menuPan = menuService.getLiveMenu(creatorId = room.member!!.id!!)
return GetRoomInfoResponse( return GetRoomInfoResponse(
roomId = roomId, roomId = roomId,
title = room.title, title = room.title,
@ -738,6 +789,7 @@ class LiveRoomService(
listenerList = roomInfo.listenerList, listenerList = roomInfo.listenerList,
managerList = roomInfo.managerList, managerList = roomInfo.managerList,
donationRankingTop3UserIds = donationRankingTop3UserIds, donationRankingTop3UserIds = donationRankingTop3UserIds,
menuPan = menuPan?.menu ?: "",
isPrivateRoom = room.type == LiveRoomType.PRIVATE, isPrivateRoom = room.type == LiveRoomType.PRIVATE,
password = room.password, password = room.password,
isActiveRoulette = isActiveRoulette isActiveRoulette = isActiveRoulette

View File

@ -19,6 +19,7 @@ data class GetRoomInfoResponse(
val listenerList: List<LiveRoomMember>, val listenerList: List<LiveRoomMember>,
val managerList: List<LiveRoomMember>, val managerList: List<LiveRoomMember>,
val donationRankingTop3UserIds: List<Long>, val donationRankingTop3UserIds: List<Long>,
val menuPan: String,
val isPrivateRoom: Boolean = false, val isPrivateRoom: Boolean = false,
val password: String? = null, val password: String? = null,
val isActiveRoulette: Boolean = false val isActiveRoulette: Boolean = false

View File

@ -3,13 +3,9 @@ package kr.co.vividnext.sodalive.live.room.menu
import kr.co.vividnext.sodalive.common.ApiResponse import kr.co.vividnext.sodalive.common.ApiResponse
import kr.co.vividnext.sodalive.common.SodaException import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.member.Member
import kr.co.vividnext.sodalive.member.MemberRole
import org.springframework.security.access.prepost.PreAuthorize import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.security.core.annotation.AuthenticationPrincipal import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController import org.springframework.web.bind.annotation.RestController
@ -17,7 +13,7 @@ import org.springframework.web.bind.annotation.RestController
@RestController @RestController
@RequestMapping("/live/room/menu") @RequestMapping("/live/room/menu")
class LiveRoomMenuController(private val service: LiveRoomMenuService) { class LiveRoomMenuController(private val service: LiveRoomMenuService) {
@GetMapping("/creator") @GetMapping("/all")
@PreAuthorize("hasRole('CREATOR')") @PreAuthorize("hasRole('CREATOR')")
fun getAllLiveMenu( fun getAllLiveMenu(
@RequestParam creatorId: Long, @RequestParam creatorId: Long,
@ -27,40 +23,4 @@ class LiveRoomMenuController(private val service: LiveRoomMenuService) {
ApiResponse.ok(service.getAllLiveMenu(creatorId = creatorId, memberId = member.id!!)) ApiResponse.ok(service.getAllLiveMenu(creatorId = creatorId, memberId = member.id!!))
} }
@PostMapping
@PreAuthorize("hasRole('CREATOR')")
fun createLiveMenu(
@RequestBody request: CreateLiveMenuRequest,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null || member.role != MemberRole.CREATOR) {
throw SodaException("로그인 정보를 확인해주세요.")
}
ApiResponse.ok(service.createLiveMenu(memberId = member.id!!, request = request))
}
@PutMapping
@PreAuthorize("hasRole('CREATOR')")
fun updateLiveMenu(
@RequestBody request: UpdateLiveMenuRequest,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null || member.role != MemberRole.CREATOR) {
throw SodaException("로그인 정보를 확인해주세요.")
}
ApiResponse.ok(service.updateLiveMenu(memberId = member.id!!, request = request))
}
@GetMapping
fun getMenu(
@RequestParam creatorId: Long,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(service.getLiveMenu(creatorId = creatorId))
}
} }

View File

@ -22,8 +22,13 @@ class LiveRoomMenuService(
fun createLiveMenu(memberId: Long, request: CreateLiveMenuRequest): Boolean { fun createLiveMenu(memberId: Long, request: CreateLiveMenuRequest): Boolean {
liveMenuValidate(menu = request.menu) liveMenuValidate(menu = request.menu)
if (request.isActive) {
val menuList = repository.findByCreatorId(creatorId = memberId) val menuList = repository.findByCreatorId(creatorId = memberId)
if (menuList.size >= 3) {
throw SodaException("메뉴판의 최대개수는 3개입니다.")
}
if (request.isActive) {
menuList.forEach { menuList.forEach {
it.isActive = false it.isActive = false
repository.save(it) repository.save(it)
@ -41,7 +46,7 @@ class LiveRoomMenuService(
return request.isActive return request.isActive
} }
fun updateLiveMenu(memberId: Long, request: UpdateLiveMenuRequest): Boolean { fun updateLiveMenu(memberId: Long, request: UpdateLiveMenuRequest) {
liveMenuValidate(menu = request.menu) liveMenuValidate(menu = request.menu)
val menuList = repository.findByCreatorId(creatorId = memberId) val menuList = repository.findByCreatorId(creatorId = memberId)
@ -49,12 +54,7 @@ class LiveRoomMenuService(
throw SodaException("잘못된 요청입니다.") throw SodaException("잘못된 요청입니다.")
} }
var isActive = false
menuList.forEach { menuList.forEach {
if (request.isActive || it.isActive) {
isActive = true
}
if (it.id == request.id) { if (it.id == request.id) {
it.menu = request.menu it.menu = request.menu
it.isActive = request.isActive it.isActive = request.isActive
@ -64,11 +64,9 @@ class LiveRoomMenuService(
repository.save(it) repository.save(it)
} }
} }
return isActive
} }
fun getLiveMenu(creatorId: Long): GetMenuResponse { fun getLiveMenu(creatorId: Long): GetMenuResponse? {
val menuList = repository.findByCreatorId(creatorId = creatorId) val menuList = repository.findByCreatorId(creatorId = creatorId)
if (menuList.isEmpty()) { if (menuList.isEmpty()) {
@ -84,12 +82,21 @@ class LiveRoomMenuService(
} }
if (activeMenu == null || activeMenu.menu.isEmpty()) { if (activeMenu == null || activeMenu.menu.isEmpty()) {
throw SodaException("설정된 메뉴판이 없습니다.") return null
} }
return GetMenuResponse(id = activeMenu.id, menu = activeMenu.menu) return GetMenuResponse(id = activeMenu.id, menu = activeMenu.menu)
} }
fun deactivateAll(memberId: Long) {
val menuList = repository.findByCreatorId(creatorId = memberId)
menuList.forEach {
it.isActive = false
repository.save(it)
}
}
private fun liveMenuValidate(menu: String) { private fun liveMenuValidate(menu: String) {
if (menu.isBlank()) { if (menu.isBlank()) {
throw SodaException("메뉴판은 빈칸일 수 없습니다.") throw SodaException("메뉴판은 빈칸일 수 없습니다.")