Skip to content

Instantly share code, notes, and snippets.

@beyondxscratch
Last active August 20, 2020 17:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save beyondxscratch/c9622935b2a80769acad6afe3fdf5aeb to your computer and use it in GitHub Desktop.
Save beyondxscratch/c9622935b2a80769acad6afe3fdf5aeb to your computer and use it in GitHub Desktop.
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)
internal class VideosDetails(val items: List<VideoDetails>)
internal class VideoDetails(val id: String, val contentDetails: ContentDetails)
internal class ContentDetails(val duration: Duration)
@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