diff --git a/docs/20260324_라이브생성_19금방전환로직추가.md b/docs/20260324_라이브생성_19금방전환로직추가.md new file mode 100644 index 00000000..dddfb0b9 --- /dev/null +++ b/docs/20260324_라이브생성_19금방전환로직추가.md @@ -0,0 +1,39 @@ +# 20260324 라이브 생성 시 19금 방 전환 로직 추가 + +## 목적 +- 라이브 생성(createLiveRoom) 시 태그 기준으로 `room.isAdult` 전환 조건을 확장한다. +- 기존 문자열 매칭("음담패설") 조건은 유지하고, `tag.isAdult = true`인 경우에도 19금 방으로 전환한다. + +## 범위 +- `LiveRoomService.createLiveRoom`의 태그 처리 구간. +- 테스트/빌드 회귀 확인. + +## 구현 체크리스트 +- [x] 기존 문자열 조건 유지: `tag.tag.contains("음담패설")` → `room.isAdult = true` +- [x] 추가 조건 구현: `tag.isAdult == true` → `room.isAdult = true` +- [x] 리팩토링: `isAdultTag(LiveTag)` 보조 함수 추출 및 태그 루프 내 부수효과 제거 +- [x] 리팩토링: 태그 기반 19금 여부를 누적 계산 후 최종 한 번만 `room.isAdult` 반영 +- [x] 코드 스타일/네이밍/예외 규칙 준수(AGENTS.md) +- [x] `./gradlew test` 실행으로 회귀 확인 + +## 변경 파일 +- `src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt` + +## 검증 계획 +1차 구현 +- 무엇을: 라이브 생성 시 태그에 `isAdult=true`가 포함되면 `room.isAdult`가 true로 설정되는지 확인 +- 왜: 19금 태그를 구조적으로 식별해 19금 방 전환을 정확히 반영하기 위함 +- 어떻게: + - 명령: `./gradlew test` + - 기대: 빌드 및 모든 테스트 통과(회귀 없음) + +2차(수동) 확인 +- 무엇을: 태그가 `음담패설` 또는 `isAdult=true`일 때 19금 전환되는지 로직 리뷰(보조 함수 경유) +- 왜: 런타임 리스크 없이 조건 충족 여부를 빠르게 확인 +- 어떻게: 코드 라인 수동 점검 + - 위치: `LiveRoomService.isAdultTag` 및 `createLiveRoom`의 태그 forEach 블록 + - 기대: 두 조건 중 하나라도 만족 시 `room.isAdult = true` + +## 정정/추가 메모 +- 현 단계에서 공개 API 스키마 변경 없음. +- 도메인 예외/응답 포맷 변경 없음. diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt index 1a49ac8b..571df5e1 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt @@ -55,6 +55,7 @@ import kr.co.vividnext.sodalive.live.room.menu.UpdateLiveMenuRequest import kr.co.vividnext.sodalive.live.room.visit.LiveRoomVisitService import kr.co.vividnext.sodalive.live.roulette.NewRouletteRepository import kr.co.vividnext.sodalive.live.signature.SignatureCanRepository +import kr.co.vividnext.sodalive.live.tag.LiveTag import kr.co.vividnext.sodalive.live.tag.LiveTagRepository import kr.co.vividnext.sodalive.member.DonationRankingPeriod import kr.co.vividnext.sodalive.member.Gender @@ -125,6 +126,12 @@ class LiveRoomService( ) { private val tokenLocks: MutableMap = mutableMapOf() + // 태그가 성인(19금) 판정에 해당하는지 여부를 계산한다. + private fun isAdultTag(tag: LiveTag): Boolean { + // 기존 문자열 기반 조건("음담패설")을 유지하고, 태그 속성의 isAdult도 함께 평가한다. + return tag.tag.contains("음담패설") || tag.isAdult + } + private fun formatMessage(key: String, vararg args: Any): String { val template = messageSource.getMessage(key, langContext.lang).orEmpty() return if (args.isNotEmpty()) { @@ -425,17 +432,22 @@ class LiveRoomService( "${beginDateTime.hour}_${beginDateTime.minute}" } - request.tags.forEach { - val tag = tagRepository.findByTag(it) + var isAdultByTags = false + request.tags.forEach { tagText -> + val tag = tagRepository.findByTag(tagText) if (tag != null) { room.tags.add(LiveRoomTag(room, tag)) - - if (tag.tag.contains("음담패설")) { - room.isAdult = true + if (isAdultTag(tag)) { + isAdultByTags = true } } } + // 태그 판정 결과를 한 번에 반영해 부수효과를 최소화한다. + if (isAdultByTags) { + room.isAdult = true + } + val createdRoom = repository.save(room) // 이미지 업로드 if (coverImage != null) {