feat(creator): 채널 라이브 탭 응답 조립을 추가한다

This commit is contained in:
2026-06-17 20:19:38 +09:00
parent 90c0af0c8b
commit f78772b613
3 changed files with 237 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
package kr.co.vividnext.sodalive.v2.api.creator.channel.live.application
import kr.co.vividnext.sodalive.member.Member
import kr.co.vividnext.sodalive.v2.api.creator.channel.live.dto.CreatorChannelLiveTabResponse
import kr.co.vividnext.sodalive.v2.common.domain.ContentSort
import kr.co.vividnext.sodalive.v2.creator.channel.live.application.CreatorChannelLiveQueryService
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDateTime
@Service
@Transactional(readOnly = true)
class CreatorChannelLiveFacade(
private val creatorChannelLiveQueryService: CreatorChannelLiveQueryService
) {
fun getLiveTab(
creatorId: Long,
viewer: Member,
sort: ContentSort,
page: Int,
size: Int,
now: LocalDateTime = LocalDateTime.now()
): CreatorChannelLiveTabResponse {
return CreatorChannelLiveTabResponse.from(
creatorChannelLiveQueryService.getLiveTab(
creatorId = creatorId,
viewer = viewer,
sort = sort,
page = page,
size = size,
now = now
)
)
}
}

View File

@@ -0,0 +1,101 @@
package kr.co.vividnext.sodalive.v2.api.creator.channel.live.dto
import com.fasterxml.jackson.annotation.JsonProperty
import kr.co.vividnext.sodalive.v2.common.domain.ContentSort
import kr.co.vividnext.sodalive.v2.creator.channel.live.domain.CreatorChannelAudioContent
import kr.co.vividnext.sodalive.v2.creator.channel.live.domain.CreatorChannelLive
import kr.co.vividnext.sodalive.v2.creator.channel.live.domain.CreatorChannelLiveTab
import java.time.LocalDateTime
import java.time.ZoneOffset
data class CreatorChannelLiveTabResponse(
val liveReplayContentCount: Int,
val currentLive: CreatorChannelLiveResponse?,
val liveReplayContents: List<CreatorChannelAudioContentResponse>,
val sort: ContentSort,
val page: Int,
val size: Int,
@JsonProperty("hasNext")
val hasNext: Boolean
) {
companion object {
fun from(tab: CreatorChannelLiveTab): CreatorChannelLiveTabResponse {
return CreatorChannelLiveTabResponse(
liveReplayContentCount = tab.liveReplayContentCount,
currentLive = tab.currentLive?.let(CreatorChannelLiveResponse::from),
liveReplayContents = tab.liveReplayContents.map(CreatorChannelAudioContentResponse::from),
sort = tab.sort,
page = tab.page.page,
size = tab.page.size,
hasNext = tab.hasNext
)
}
}
}
data class CreatorChannelAudioContentResponse(
val audioContentId: Long,
val title: String,
val duration: String?,
val imageUrl: String?,
val price: Int,
@JsonProperty("isAdult")
val isAdult: Boolean,
@JsonProperty("isPointAvailable")
val isPointAvailable: Boolean,
@JsonProperty("isFirstContent")
val isFirstContent: Boolean,
val seriesName: String?,
@JsonProperty("isOriginalSeries")
val isOriginalSeries: Boolean?,
@JsonProperty("isOwned")
val isOwned: Boolean,
@JsonProperty("isRented")
val isRented: Boolean
) {
companion object {
fun from(content: CreatorChannelAudioContent): CreatorChannelAudioContentResponse {
return CreatorChannelAudioContentResponse(
audioContentId = content.audioContentId,
title = content.title,
duration = content.duration,
imageUrl = content.imageUrl,
price = content.price,
isAdult = content.isAdult,
isPointAvailable = content.isPointAvailable,
isFirstContent = content.isFirstContent,
seriesName = content.seriesName,
isOriginalSeries = content.isOriginalSeries,
isOwned = content.isOwned,
isRented = content.isRented
)
}
}
}
data class CreatorChannelLiveResponse(
val liveId: Long,
val title: String,
val coverImageUrl: String?,
val beginDateTimeUtc: String,
val price: Int,
@JsonProperty("isAdult")
val isAdult: Boolean
) {
companion object {
fun from(live: CreatorChannelLive): CreatorChannelLiveResponse {
return CreatorChannelLiveResponse(
liveId = live.liveId,
title = live.title,
coverImageUrl = live.coverImageUrl,
beginDateTimeUtc = live.beginDateTime.toUtcIso(),
price = live.price,
isAdult = live.isAdult
)
}
}
}
private fun LocalDateTime.toUtcIso(): String {
return atOffset(ZoneOffset.UTC).toInstant().toString()
}