feat: 라이브 메인 API

- 기존에 섹션별로 따로따로 호출하던 것을 하나로 합쳐서 호출할 수 있도록 API 추가
This commit is contained in:
2025-07-21 15:14:47 +09:00
parent 8e877a6366
commit 046c163e6f
11 changed files with 212 additions and 6 deletions

View File

@@ -0,0 +1,33 @@
package kr.co.vividnext.sodalive.api.live
import kr.co.vividnext.sodalive.common.ApiResponse
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.member.Member
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("/api/live")
class LiveApiController(
private val service: LiveApiService
) {
@GetMapping
fun fetchData(
@RequestParam timezone: String,
@RequestParam("contentType", required = false) contentType: ContentType? = null,
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
ApiResponse.ok(
service.fetchData(
isAdultContentVisible = isAdultContentVisible ?: true,
contentType = contentType ?: ContentType.ALL,
timezone = timezone,
member = member
)
)
}
}

View File

@@ -0,0 +1,106 @@
package kr.co.vividnext.sodalive.api.live
import kr.co.vividnext.sodalive.content.AudioContentService
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.explorer.ExplorerQueryRepository
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.CreatorCommunityService
import kr.co.vividnext.sodalive.live.recommend.LiveRecommendService
import kr.co.vividnext.sodalive.live.room.LiveRoomService
import kr.co.vividnext.sodalive.live.room.LiveRoomStatus
import kr.co.vividnext.sodalive.member.Member
import kr.co.vividnext.sodalive.member.block.BlockMemberRepository
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
@Service
class LiveApiService(
private val liveService: LiveRoomService,
private val contentService: AudioContentService,
private val recommendService: LiveRecommendService,
private val creatorCommunityService: CreatorCommunityService,
private val blockMemberRepository: BlockMemberRepository,
private val explorerQueryRepository: ExplorerQueryRepository
) {
fun fetchData(
isAdultContentVisible: Boolean,
contentType: ContentType,
timezone: String,
member: Member?
): LiveMainResponse {
val memberId = member?.id
val isAdult = member?.auth != null && isAdultContentVisible
val liveOnAirRoomList = liveService.getRoomList(
dateString = null,
status = LiveRoomStatus.NOW,
isAdultContentVisible = isAdultContentVisible,
pageable = Pageable.ofSize(20),
member = member,
timezone = timezone
)
val communityPostList = if (memberId != null) {
creatorCommunityService.getLatestPostListFromCreatorsYouFollow(
timezone = timezone,
memberId = memberId,
isAdult = isAdult
)
} else {
listOf()
}
val recommendLiveList = recommendService.getRecommendLive(member)
val latestFinishedLiveList = liveService.getLatestFinishedLive(member)
.map {
if (memberId != null) {
it.isFollowing = explorerQueryRepository.getCreatorFollowing(
creatorId = it.memberId,
memberId = memberId
)?.isFollow ?: false
}
it
}
val replayLive = contentService.getLatestContentByTheme(
theme = listOf("다시듣기"),
contentType = contentType,
isFree = false,
isAdult = isAdult
)
.filter { content ->
if (memberId != null) {
!blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = content.creatorId)
} else {
true
}
}
val followingChannelList = if (memberId != null) {
recommendService.getFollowingChannelList(member)
} else {
listOf()
}
val liveReservationRoomList = liveService.getRoomList(
dateString = null,
status = LiveRoomStatus.RESERVATION,
isAdultContentVisible = isAdultContentVisible,
pageable = Pageable.ofSize(10),
member = member,
timezone = timezone
)
return LiveMainResponse(
liveOnAirRoomList = liveOnAirRoomList,
communityPostList = communityPostList,
recommendLiveList = recommendLiveList,
latestFinishedLiveList = latestFinishedLiveList,
replayLive = replayLive,
followingChannelList = followingChannelList,
liveReservationRoomList = liveReservationRoomList
)
}
}

View File

@@ -0,0 +1,18 @@
package kr.co.vividnext.sodalive.api.live
import kr.co.vividnext.sodalive.content.AudioContentMainItem
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.GetCommunityPostListResponse
import kr.co.vividnext.sodalive.live.recommend.GetRecommendChannelResponse
import kr.co.vividnext.sodalive.live.recommend.GetRecommendLiveResponse
import kr.co.vividnext.sodalive.live.room.GetLatestFinishedLiveResponse
import kr.co.vividnext.sodalive.live.room.GetRoomListResponse
data class LiveMainResponse(
val liveOnAirRoomList: List<GetRoomListResponse>,
val communityPostList: List<GetCommunityPostListResponse>,
val recommendLiveList: List<GetRecommendLiveResponse>,
val latestFinishedLiveList: List<GetLatestFinishedLiveResponse>,
val replayLive: List<AudioContentMainItem>,
val followingChannelList: List<GetRecommendChannelResponse>,
val liveReservationRoomList: List<GetRoomListResponse>
)