package kr.co.vividnext.sodalive.content import kr.co.vividnext.sodalive.common.ApiResponse import kr.co.vividnext.sodalive.common.SodaException import kr.co.vividnext.sodalive.content.like.PutAudioContentLikeRequest import kr.co.vividnext.sodalive.member.Member import org.springframework.data.domain.Pageable import org.springframework.lang.Nullable import org.springframework.security.access.prepost.PreAuthorize import org.springframework.security.core.annotation.AuthenticationPrincipal import org.springframework.web.bind.annotation.DeleteMapping import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.PutMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RequestPart import org.springframework.web.bind.annotation.RestController import org.springframework.web.multipart.MultipartFile import java.time.DayOfWeek import java.time.LocalDateTime import java.time.temporal.TemporalAdjusters @RestController @RequestMapping("/audio-content") class AudioContentController(private val service: AudioContentService) { @PostMapping @PreAuthorize("hasRole('CREATOR')") fun createAudioContent( @Nullable @RequestPart("contentFile") contentFile: MultipartFile?, @RequestPart("coverImage") coverImage: MultipartFile?, @RequestPart("request") requestString: String, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok( service.createAudioContent( contentFile = contentFile, coverImage = coverImage, requestString = requestString, member = member ) ) } @PutMapping @PreAuthorize("hasRole('CREATOR')") fun modifyAudioContent( @Nullable @RequestPart("coverImage") coverImage: MultipartFile?, @RequestPart("request") requestString: String, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok( service.modifyAudioContent( coverImage = coverImage, requestString = requestString, member = member ) ) } @PutMapping("/upload-complete") @PreAuthorize("hasAnyRole('ADMIN', 'BOT')") fun uploadComplete( @RequestBody request: UploadCompleteRequest, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok( service.uploadComplete( contentId = request.contentId, content = request.contentPath, duration = request.duration ) ) } @DeleteMapping("/{id}") @PreAuthorize("hasRole('CREATOR')") fun deleteAudioContent( @PathVariable id: Long, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok( service.deleteAudioContent( audioContentId = id, member = member ) ) } @GetMapping fun getAudioContentList( @RequestParam("creator-id") creatorId: Long, @RequestParam("sort-type", required = false) sortType: SortType? = SortType.NEWEST, @RequestParam("category-id", required = false) categoryId: Long? = 0, @RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null, @RequestParam("contentType", required = false) contentType: ContentType? = null, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?, pageable: Pageable ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok( service.getAudioContentList( creatorId = creatorId, sortType = sortType ?: SortType.NEWEST, categoryId = categoryId ?: 0, isAdultContentVisible = isAdultContentVisible ?: true, contentType = contentType ?: ContentType.ALL, member = member, offset = pageable.offset, limit = pageable.pageSize.toLong() ) ) } @GetMapping("/{id}") fun getDetail( @PathVariable id: Long, @RequestParam timezone: String, @RequestParam(required = false) languageCode: String? = null, @RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok( service.getDetail( id = id, member = member, isAdultContentVisible = isAdultContentVisible ?: true, timezone = timezone, languageCode = languageCode ) ) } @GetMapping("/{id}/generate-url") fun generateUrl( @PathVariable id: Long, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.generateUrl(contentId = id, member = member)) } @PostMapping("/playback-tracking") fun addAllPlaybackTracking( @RequestBody request: AddAllPlaybackTrackingRequest, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.addAllPlaybackTracking(request, member)) } @PutMapping("/like") fun audioContentLike( @RequestBody request: PutAudioContentLikeRequest, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.audioContentLike(request, member)) } @GetMapping("/ranking-sort-type") fun getAudioContentRankingSort( @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.getContentRankingSortTypeList()) } @GetMapping("/ranking") fun getAudioContentRanking( @RequestParam("sort-type", required = false) sortType: String? = "매출", @RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null, @RequestParam("contentType", required = false) contentType: ContentType? = null, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?, pageable: Pageable ) = run { val currentDateTime = LocalDateTime.now() val startDate = currentDateTime .withHour(15) .withMinute(0) .withSecond(0) .minusWeeks(1) .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)) val endDate = startDate .plusDays(7) ApiResponse.ok( service.getAudioContentRanking( isAdult = member?.auth != null && (isAdultContentVisible ?: true), contentType = contentType ?: ContentType.ALL, startDate = startDate, endDate = endDate, offset = pageable.offset, limit = pageable.pageSize.toLong(), sortType = sortType ?: "매출" ) ) } @PostMapping("/pin-to-the-top/{id}") @PreAuthorize("hasRole('CREATOR')") fun pinToTheTop( @PathVariable id: Long, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.pinToTheTop(contentId = id, member = member)) } @PutMapping("/unpin-at-the-top/{id}") @PreAuthorize("hasRole('CREATOR')") fun unpinAtTheTop( @PathVariable id: Long, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.unpinAtTheTop(contentId = id, member = member)) } @GetMapping("/all") fun getAllContents( @RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null, @RequestParam("contentType", required = false) contentType: ContentType? = null, @RequestParam("isFree", required = false) isFree: Boolean? = null, @RequestParam("isPointAvailableOnly", required = false) isPointAvailableOnly: Boolean? = null, @RequestParam("sort-type", required = false) sortType: SortType? = SortType.NEWEST, @RequestParam("theme", required = false) theme: String? = null, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?, pageable: Pageable ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok( service.getLatestContentByTheme( theme = if (theme == null) listOf() else listOf(theme), contentType = contentType ?: ContentType.ALL, offset = pageable.offset, limit = pageable.pageSize.toLong(), sortType = sortType ?: SortType.NEWEST, isFree = isFree ?: false, isAdult = (isAdultContentVisible ?: true) && member.auth != null, isPointAvailableOnly = isPointAvailableOnly ?: false ) ) } @GetMapping("/replay-live") fun replayLive( @RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null, @RequestParam("contentType", required = false) contentType: ContentType? = null, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { ApiResponse.ok( service.getLatestContentByTheme( theme = listOf("다시듣기"), contentType = contentType ?: ContentType.ALL, isFree = false, isAdult = if (member != null) { (isAdultContentVisible ?: true) && member.auth != null } else { false } ) ) } }