feat(creator): 스케줄 성인 노출 정책을 적용한다

This commit is contained in:
2026-06-12 17:23:37 +09:00
parent 6fa7044220
commit abc3e8e9aa
4 changed files with 28 additions and 8 deletions

View File

@@ -68,7 +68,8 @@ data class CreatorChannelSchedule(
val scheduledAt: LocalDateTime, val scheduledAt: LocalDateTime,
val title: String, val title: String,
val type: CreatorActivityType, val type: CreatorActivityType,
val targetId: Long val targetId: Long,
val isAdult: Boolean
) )
data class CreatorChannelSeries( data class CreatorChannelSeries(

View File

@@ -6,10 +6,12 @@ import java.time.LocalDateTime
class CreatorChannelHomeQueryPolicy { class CreatorChannelHomeQueryPolicy {
fun limitSchedules( fun limitSchedules(
schedules: List<CreatorChannelSchedule>, schedules: List<CreatorChannelSchedule>,
now: LocalDateTime now: LocalDateTime,
canViewAdultContent: Boolean
): List<CreatorChannelSchedule> { ): List<CreatorChannelSchedule> {
return schedules return schedules
.filter { it.scheduledAt > now } .filter { it.scheduledAt > now }
.filter { canViewAdultContent || !it.isAdult }
.sortedWith(compareBy<CreatorChannelSchedule> { it.scheduledAt }.thenBy { it.type.scheduleOrder() }) .sortedWith(compareBy<CreatorChannelSchedule> { it.scheduledAt }.thenBy { it.type.scheduleOrder() })
.take(3) .take(3)
} }

View File

@@ -165,7 +165,8 @@ class CreatorChannelHomeQueryServiceTest {
scheduledAt = LocalDateTime.of(2026, 6, 12, 3, 0), scheduledAt = LocalDateTime.of(2026, 6, 12, 3, 0),
title = "schedule", title = "schedule",
type = CreatorActivityType.LIVE, type = CreatorActivityType.LIVE,
targetId = 501L targetId = 501L,
isAdult = false
) )
), ),
audioContents = listOf( audioContents = listOf(

View File

@@ -22,7 +22,7 @@ class CreatorChannelHomeQueryPolicyTest {
schedule(targetId = 3L, scheduledAt = LocalDateTime.of(2026, 6, 12, 12, 0)) schedule(targetId = 3L, scheduledAt = LocalDateTime.of(2026, 6, 12, 12, 0))
) )
val limited = policy.limitSchedules(schedules, now) val limited = policy.limitSchedules(schedules, now, canViewAdultContent = true)
assertEquals(listOf(1L, 2L, 3L), limited.map { it.targetId }) assertEquals(listOf(1L, 2L, 3L), limited.map { it.targetId })
} }
@@ -37,7 +37,7 @@ class CreatorChannelHomeQueryPolicyTest {
schedule(targetId = 3L, scheduledAt = now.plusMinutes(1)) schedule(targetId = 3L, scheduledAt = now.plusMinutes(1))
) )
val limited = policy.limitSchedules(schedules, now) val limited = policy.limitSchedules(schedules, now, canViewAdultContent = true)
assertEquals(listOf(3L), limited.map { it.targetId }) assertEquals(listOf(3L), limited.map { it.targetId })
} }
@@ -51,11 +51,25 @@ class CreatorChannelHomeQueryPolicyTest {
schedule(targetId = 1L, scheduledAt = scheduledAt, type = CreatorActivityType.LIVE) schedule(targetId = 1L, scheduledAt = scheduledAt, type = CreatorActivityType.LIVE)
) )
val limited = policy.limitSchedules(schedules, scheduledAt.minusMinutes(1)) val limited = policy.limitSchedules(schedules, scheduledAt.minusMinutes(1), canViewAdultContent = true)
assertEquals(listOf(CreatorActivityType.LIVE, CreatorActivityType.AUDIO), limited.map { it.type }) assertEquals(listOf(CreatorActivityType.LIVE, CreatorActivityType.AUDIO), limited.map { it.type })
} }
@Test
@DisplayName("조회자의 성인 노출 정책이 false이면 성인 스케줄을 제외한다")
fun shouldExcludeAdultSchedulesWhenViewerCannotViewAdultContent() {
val now = LocalDateTime.of(2026, 6, 12, 9, 0)
val schedules = listOf(
schedule(targetId = 1L, scheduledAt = now.plusMinutes(1), isAdult = true),
schedule(targetId = 2L, scheduledAt = now.plusMinutes(2), isAdult = false)
)
val limited = policy.limitSchedules(schedules, now, canViewAdultContent = false)
assertEquals(listOf(2L), limited.map { it.targetId })
}
@Test @Test
@DisplayName("오디오 목록에서는 latestAudioContentId와 같은 콘텐츠를 제외한다") @DisplayName("오디오 목록에서는 latestAudioContentId와 같은 콘텐츠를 제외한다")
fun shouldExcludeLatestAudioContent() { fun shouldExcludeLatestAudioContent() {
@@ -86,13 +100,15 @@ class CreatorChannelHomeQueryPolicyTest {
private fun schedule( private fun schedule(
targetId: Long, targetId: Long,
scheduledAt: LocalDateTime, scheduledAt: LocalDateTime,
type: CreatorActivityType = CreatorActivityType.LIVE type: CreatorActivityType = CreatorActivityType.LIVE,
isAdult: Boolean = false
): CreatorChannelSchedule { ): CreatorChannelSchedule {
return CreatorChannelSchedule( return CreatorChannelSchedule(
scheduledAt = scheduledAt, scheduledAt = scheduledAt,
title = "schedule-$targetId", title = "schedule-$targetId",
type = type, type = type,
targetId = targetId targetId = targetId,
isAdult = isAdult
) )
} }