This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
internal class Videos(val items: List<Video>) { | |
fun toTalkBuilders(): List<Talk.Builder> { | |
return items.map(Video::toTalkBuilder) | |
} | |
} | |
internal class Video(val id: VideoId, private val snippet: Snippet) { | |
internal fun toTalkBuilder(): Talk.Builder { | |
val videoId = id.videoId | |
return Talk.with { | |
id = videoId | |
title = snippet.title | |
} | |
} | |
} | |
internal class VideoId(val videoId: String) | |
internal class Snippet(val title: String) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
internal class VideosDetails(val items: List<VideoDetails>) | |
internal class VideoDetails(val id: String, val contentDetails: ContentDetails) | |
internal class ContentDetails(val duration: Duration) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Component | |
@Conditional(NoSearchTalksAlreadyPresent::class) | |
class YouTubeSearchTalks( | |
restTemplateBuilder: RestTemplateBuilder, | |
@Value("\${youtube.api.base-uri}") val youtubeApiBaseUri: String, | |
@Value("\${youtube.api.key}") val apiKey: String, | |
@Value("\${talks.max-number}") override val maxNumberOfTalks: Int) : SearchTalks { | |
private val restTemplate = restTemplateBuilder.build() | |
private val devoxxChannelId = "UCCBVCTuk6uJrN3iFV_3vurg" | |
override fun forTopics(topics: Set<Topic>): Set<Talk> { | |
val videosWithoutDuration = retrieveVideosWithoutDuration(topics) | |
val videosDuration = retrieveVideosDuration(videosWithoutDuration) | |
val talksWithoutDuration = videosWithoutDuration.toTalkBuilders() | |
return talksWithoutDuration.buildWithDurationsFrom(videosDuration) | |
} | |
private fun retrieveVideosWithoutDuration(topics: Set<Topic>): Videos { | |
val searchRequest = searchRequest(topics) | |
return restTemplate.getForObject(searchRequest, Videos::class.java)!! | |
} | |
private fun retrieveVideosDuration(videosWithoutDuration: Videos): Map<String, Duration> { | |
return videosWithoutDuration | |
.extractVideoIds() | |
.let { toVideosListOptions(it) } | |
.let { toVideosListRequest(it) } | |
.let { restTemplate.getForObject(it, VideosDetails::class.java)!! } | |
.idToDurationMap() | |
} | |
private fun searchRequest(topics: Set<Topic>): URI { | |
return UriComponentsBuilder.fromUriString(youtubeApiBaseUri) | |
.path("/search") | |
.queryParams(searchOptions(topics)) | |
.build() | |
.toUri() | |
} | |
private fun searchOptions(topics: Set<Topic>): MultiValueMap<String, String> { | |
val options: MultiValueMap<String, String> = LinkedMultiValueMap() | |
options["part"] = "id,snippet" | |
options["channelId"] = devoxxChannelId | |
options["maxResults"] = maxNumberOfTalks.toString() | |
options["q"] = topics.joinToString("|") { it.name } | |
options["type"] = "video" | |
options["fields"] = "items(id/kind,id/videoId,snippet/title,snippet/thumbnails/default/url)" | |
options["key"] = apiKey | |
return options | |
} | |
private fun Talk.Builder.withDurationFrom(videosDuration: Map<String, Duration>): Talk.Builder { | |
return this.apply { duration = videosDuration.getValue(id) } | |
} | |
private fun Iterable<Talk.Builder>.buildWithDurationsFrom(videosDuration: Map<String, Duration>): Set<Talk> { | |
return this.map { it.withDurationFrom(videosDuration) } | |
.map(Talk.Builder::build) | |
.toSet() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment