feat(content-preference): 콘텐츠 조회 설정 서버 저장 전환을 반영한다
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
package kr.co.vividnext.sodalive.live.recommend
|
||||
|
||||
import org.springframework.cache.annotation.Cacheable
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
@Service
|
||||
class LiveRecommendCacheService(
|
||||
private val repository: LiveRecommendRepository
|
||||
) {
|
||||
@Cacheable(
|
||||
cacheNames = ["cache_ttl_3_hours"],
|
||||
key = "'getRecommendLive:' + (#memberId ?: 'guest') + ':' + #isAdult"
|
||||
)
|
||||
fun getRecommendLive(memberId: Long?, isAdult: Boolean): List<GetRecommendLiveResponse> {
|
||||
return repository.getRecommendLive(
|
||||
memberId = memberId,
|
||||
isAdult = isAdult
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -3,29 +3,37 @@ package kr.co.vividnext.sodalive.live.recommend
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberRole
|
||||
import kr.co.vividnext.sodalive.member.block.BlockMemberRepository
|
||||
import org.springframework.cache.annotation.Cacheable
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||
import org.springframework.data.domain.Pageable
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
|
||||
@Service
|
||||
class LiveRecommendService(
|
||||
private val repository: LiveRecommendRepository,
|
||||
private val blockMemberRepository: BlockMemberRepository
|
||||
private val blockMemberRepository: BlockMemberRepository,
|
||||
private val memberContentPreferenceService: MemberContentPreferenceService,
|
||||
private val liveRecommendCacheService: LiveRecommendCacheService
|
||||
) {
|
||||
@Transactional(readOnly = true)
|
||||
@Cacheable(
|
||||
cacheNames = ["cache_ttl_3_hours"],
|
||||
key = "'getRecommendLive:' + (#member?.id ?: 'guest')"
|
||||
)
|
||||
fun getRecommendLive(member: Member?): List<GetRecommendLiveResponse> {
|
||||
return repository.getRecommendLive(
|
||||
val isAdult = if (member != null) {
|
||||
memberContentPreferenceService.getStoredPreference(member).isAdult
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
return liveRecommendCacheService.getRecommendLive(
|
||||
memberId = member?.id,
|
||||
isAdult = member?.auth != null
|
||||
isAdult = isAdult
|
||||
)
|
||||
}
|
||||
|
||||
fun getRecommendChannelList(member: Member?): List<GetRecommendChannelResponse> {
|
||||
val isAdult = if (member != null) {
|
||||
memberContentPreferenceService.getStoredPreference(member).isAdult
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
val onAirChannelList = repository.getOnAirRecommendChannelList(
|
||||
isBlocked = {
|
||||
if (member != null) {
|
||||
@@ -35,7 +43,7 @@ class LiveRecommendService(
|
||||
}
|
||||
},
|
||||
isCreator = member?.role == MemberRole.CREATOR,
|
||||
isAdult = member?.auth != null
|
||||
isAdult = isAdult
|
||||
)
|
||||
|
||||
if (onAirChannelList.size >= 20) {
|
||||
@@ -60,11 +68,13 @@ class LiveRecommendService(
|
||||
}
|
||||
|
||||
fun getFollowingChannelList(member: Member): List<GetRecommendChannelResponse> {
|
||||
val isAdult = memberContentPreferenceService.getStoredPreference(member).isAdult
|
||||
|
||||
val onAirFollowingChannelList = repository.getOnAirFollowingChannelList(
|
||||
memberId = member.id!!,
|
||||
isBlocked = { isBlockedBetweenMembers(memberId = member.id!!, creatorId = it) },
|
||||
isCreator = member.role == MemberRole.CREATOR,
|
||||
isAdult = member.auth != null
|
||||
isAdult = isAdult
|
||||
)
|
||||
|
||||
if (onAirFollowingChannelList.size >= 20) {
|
||||
|
||||
@@ -43,7 +43,7 @@ class LiveRoomController(
|
||||
service.getRoomList(
|
||||
dateString,
|
||||
status,
|
||||
isAdultContentVisible ?: true,
|
||||
isAdultContentVisible,
|
||||
pageable,
|
||||
member,
|
||||
timezone
|
||||
|
||||
@@ -17,6 +17,7 @@ import kr.co.vividnext.sodalive.can.use.CanUsage
|
||||
import kr.co.vividnext.sodalive.can.use.UseCanCalculateRepository
|
||||
import kr.co.vividnext.sodalive.can.use.UseCanCalculateStatus
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.content.ContentType
|
||||
import kr.co.vividnext.sodalive.explorer.ExplorerQueryRepository
|
||||
import kr.co.vividnext.sodalive.explorer.profile.CreatorDonationRankingService
|
||||
import kr.co.vividnext.sodalive.extensions.convertLocalDateTime
|
||||
@@ -63,6 +64,8 @@ import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberRepository
|
||||
import kr.co.vividnext.sodalive.member.MemberRole
|
||||
import kr.co.vividnext.sodalive.member.block.BlockMemberRepository
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.ViewerContentPreference
|
||||
import kr.co.vividnext.sodalive.utils.generateFileName
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.cache.annotation.Cacheable
|
||||
@@ -106,6 +109,7 @@ class LiveRoomService(
|
||||
private val pushTokenRepository: PushTokenRepository,
|
||||
private val memberRepository: MemberRepository,
|
||||
private val tagRepository: LiveTagRepository,
|
||||
private val memberContentPreferenceService: MemberContentPreferenceService,
|
||||
private val canRepository: CanRepository,
|
||||
private val objectMapper: ObjectMapper,
|
||||
private val s3Uploader: S3Uploader,
|
||||
@@ -201,11 +205,13 @@ class LiveRoomService(
|
||||
fun getRoomList(
|
||||
dateString: String?,
|
||||
status: LiveRoomStatus,
|
||||
isAdultContentVisible: Boolean,
|
||||
isAdultContentVisible: Boolean?,
|
||||
pageable: Pageable,
|
||||
member: Member?,
|
||||
timezone: String
|
||||
): List<GetRoomListResponse> {
|
||||
val preference = resolvePreference(member, isAdultContentVisible)
|
||||
val isAdult = preference.isAdult
|
||||
val effectiveGender = member?.let {
|
||||
if (it.auth != null) {
|
||||
if (it.auth!!.gender == 1) Gender.MALE else Gender.FEMALE
|
||||
@@ -219,7 +225,7 @@ class LiveRoomService(
|
||||
timezone,
|
||||
memberId = member?.id,
|
||||
isCreator = member?.role == MemberRole.CREATOR,
|
||||
isAdult = true,
|
||||
isAdult = isAdult,
|
||||
effectiveGender = effectiveGender
|
||||
)
|
||||
} else if (dateString != null) {
|
||||
@@ -229,7 +235,7 @@ class LiveRoomService(
|
||||
timezone,
|
||||
memberId = member?.id,
|
||||
isCreator = member?.role == MemberRole.CREATOR,
|
||||
isAdult = member?.auth != null && isAdultContentVisible,
|
||||
isAdult = isAdult,
|
||||
effectiveGender = effectiveGender
|
||||
)
|
||||
} else {
|
||||
@@ -237,7 +243,7 @@ class LiveRoomService(
|
||||
timezone,
|
||||
isCreator = member?.role == MemberRole.CREATOR,
|
||||
memberId = member?.id,
|
||||
isAdult = member?.auth != null && isAdultContentVisible,
|
||||
isAdult = isAdult,
|
||||
effectiveGender = effectiveGender
|
||||
)
|
||||
}
|
||||
@@ -529,7 +535,8 @@ class LiveRoomService(
|
||||
throw SodaException(messageKey = "live.room.already_ended")
|
||||
}
|
||||
|
||||
if (room.isAdult && member.auth == null) {
|
||||
val preference = memberContentPreferenceService.getStoredPreference(member)
|
||||
if (room.isAdult && !preference.isAdult) {
|
||||
throw SodaException(messageKey = "live.room.adult_verification_required")
|
||||
}
|
||||
|
||||
@@ -770,6 +777,11 @@ class LiveRoomService(
|
||||
val room = repository.getLiveRoom(id = request.roomId)
|
||||
?: throw SodaException(messageKey = "live.room.not_found")
|
||||
|
||||
val preference = memberContentPreferenceService.getStoredPreference(member)
|
||||
if (room.isAdult && !preference.isAdult) {
|
||||
throw SodaException(messageKey = "live.room.adult_verification_required")
|
||||
}
|
||||
|
||||
if (
|
||||
room.member!!.id!! != member.id!! &&
|
||||
room.type == LiveRoomType.PRIVATE &&
|
||||
@@ -1458,6 +1470,23 @@ class LiveRoomService(
|
||||
return tokenLocks.computeIfAbsent(memberId) { ReentrantReadWriteLock() }
|
||||
}
|
||||
|
||||
private fun resolvePreference(member: Member?, isAdultContentVisible: Boolean?): ViewerContentPreference {
|
||||
if (member == null) {
|
||||
return ViewerContentPreference(
|
||||
countryCode = "KR",
|
||||
isAdultContentVisible = isAdultContentVisible ?: false,
|
||||
contentType = ContentType.ALL,
|
||||
isAdult = false
|
||||
)
|
||||
}
|
||||
|
||||
return memberContentPreferenceService.resolveForQuery(
|
||||
member = member,
|
||||
isAdultContentVisible = isAdultContentVisible,
|
||||
contentType = null
|
||||
)
|
||||
}
|
||||
|
||||
@Transactional
|
||||
fun likeHeart(request: LiveRoomLikeHeartRequest, member: Member) {
|
||||
val room = repository.findByIdOrNull(request.roomId)
|
||||
|
||||
@@ -2,8 +2,6 @@ package kr.co.vividnext.sodalive.live.tag
|
||||
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||
import kr.co.vividnext.sodalive.live.tag.QLiveTag.liveTag
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberRole
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
@@ -13,15 +11,15 @@ interface LiveTagRepository : JpaRepository<LiveTag, Long>, LiveTagQueryReposito
|
||||
}
|
||||
|
||||
interface LiveTagQueryRepository {
|
||||
fun getTags(member: Member, cloudFrontHost: String): List<GetLiveTagResponse>
|
||||
fun getTags(isAdult: Boolean, cloudFrontHost: String): List<GetLiveTagResponse>
|
||||
}
|
||||
|
||||
@Repository
|
||||
class LiveTagQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : LiveTagQueryRepository {
|
||||
override fun getTags(member: Member, cloudFrontHost: String): List<GetLiveTagResponse> {
|
||||
override fun getTags(isAdult: Boolean, cloudFrontHost: String): List<GetLiveTagResponse> {
|
||||
var where = liveTag.isActive.isTrue
|
||||
|
||||
if (member.role != MemberRole.ADMIN && member.auth == null) {
|
||||
if (!isAdult) {
|
||||
where = where.and(liveTag.isAdult.isFalse)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import kr.co.vividnext.sodalive.aws.s3.S3Uploader
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberRole
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||
import kr.co.vividnext.sodalive.utils.generateFileName
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
@@ -15,6 +17,7 @@ import org.springframework.web.multipart.MultipartFile
|
||||
@Service
|
||||
class LiveTagService(
|
||||
private val repository: LiveTagRepository,
|
||||
private val memberContentPreferenceService: MemberContentPreferenceService,
|
||||
|
||||
private val objectMapper: ObjectMapper,
|
||||
private val s3Uploader: S3Uploader,
|
||||
@@ -91,7 +94,15 @@ class LiveTagService(
|
||||
}
|
||||
|
||||
fun getTags(member: Member): List<GetLiveTagResponse> {
|
||||
return repository.getTags(member = member, cloudFrontHost = cloudFrontHost)
|
||||
// 관리자 화면에서는 운영 확인 목적상 성인 태그까지 전체 조회를 허용한다.
|
||||
val isAdult = if (member.role == MemberRole.ADMIN) {
|
||||
true
|
||||
} else {
|
||||
// 일반 사용자는 저장된 선호 정책(isAdult) 기준으로만 태그 노출을 제한한다.
|
||||
memberContentPreferenceService.getStoredPreference(member).isAdult
|
||||
}
|
||||
|
||||
return repository.getTags(isAdult = isAdult, cloudFrontHost = cloudFrontHost)
|
||||
}
|
||||
|
||||
fun tagExistCheck(request: CreateLiveTagRequest) {
|
||||
|
||||
Reference in New Issue
Block a user