Skip to content

Commit

Permalink
refactor(backend): move DailymotionUpdater to non Reactive API
Browse files Browse the repository at this point in the history
Related to #231
  • Loading branch information
davinkevin committed Aug 3, 2024
1 parent 8d5d51a commit 1353981
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,11 @@ fun ImageService.fetchCoverUpdateInformationOrOption(url: URI?): Mono<Optional<I
.map { Optional.of(it) }
.switchIfEmpty { Optional.empty<ItemFromUpdate.Cover>().toMono() }
}

fun ImageService.fetchCoverUpdateInformation(url: URI): ItemFromUpdate.Cover? {
val coverInformation = fetchCoverInformation(url).block()
?: return null

return ItemFromUpdate
.Cover(coverInformation.width, coverInformation.height, coverInformation.url)
}
Original file line number Diff line number Diff line change
@@ -1,71 +1,84 @@
package com.github.davinkevin.podcastserver.update.updaters.dailymotion

import com.fasterxml.jackson.annotation.JsonProperty
import com.github.davinkevin.podcastserver.extension.java.util.orNull
import com.github.davinkevin.podcastserver.service.image.ImageService
import com.github.davinkevin.podcastserver.update.fetchCoverUpdateInformation
import com.github.davinkevin.podcastserver.update.updaters.ItemFromUpdate
import com.github.davinkevin.podcastserver.update.updaters.PodcastToUpdate
import com.github.davinkevin.podcastserver.update.updaters.Type
import com.github.davinkevin.podcastserver.update.updaters.Updater
import com.github.davinkevin.podcastserver.update.fetchCoverUpdateInformationOrOption
import com.github.davinkevin.podcastserver.utils.MatcherExtractor
import org.springframework.util.DigestUtils
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.reactive.function.client.bodyToMono
import org.springframework.web.client.RestClient
import org.springframework.web.client.body
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import reactor.kotlin.core.publisher.toFlux
import reactor.kotlin.core.publisher.toMono
import reactor.kotlin.core.util.function.component1
import reactor.kotlin.core.util.function.component2
import java.net.URI
import java.time.Instant
import java.time.ZoneId
import java.time.ZonedDateTime
import com.github.davinkevin.podcastserver.service.image.ImageService

/**
* Created by kevin on 13/03/2020
*/
class DailymotionUpdater(
private val wc: WebClient,
private val image: ImageService
private val rc: RestClient,
private val image: ImageService
): Updater {

override fun signatureOf(url: URI): Mono<String> {
val userName = USER_NAME_EXTRACTOR.on(url.toASCIIString()).group(1) ?: error("username not found")

return wc
.get()
.uri("/user/{userName}/videos?fields=id", userName)
.retrieve()
.bodyToMono<DailymotionResult>()
.flatMapIterable { it.list }
.map { it.id }
.sort()
.reduce { t, u -> """$t, $u""" }
.map { DigestUtils.md5DigestAsHex(it.toByteArray()) }
.switchIfEmpty("".toMono())
override fun signatureOf(url: URI): Mono<String> = signatureOfBlocking(url).toMono()

override fun signatureOfBlocking(url: URI): String? {
val userName = USER_NAME_EXTRACTOR
.on(url.toASCIIString())
.group(1)
?: error("username not found")

val channelDetails = rc
.get()
.uri("/user/{userName}/videos?fields=id", userName)
.retrieve()
.body<DailymotionResult>()
?: return null

if (channelDetails.list.isEmpty()) {
return ""
}

val sign = channelDetails.list
.map { it.id }
.sorted()
.reduce { t, u -> """$t, $u""" }
.let { DigestUtils.md5DigestAsHex(it.toByteArray()) }

return sign
}

override fun findItems(podcast: PodcastToUpdate): Flux<ItemFromUpdate> {
return findItemsBlocking(podcast).toFlux()
}

override fun findItemsBlocking(podcast: PodcastToUpdate): List<ItemFromUpdate> {
val userName = USER_NAME_EXTRACTOR.on(podcast.url.toASCIIString()).group(1) ?: error("username not found")

return wc
.get()
.uri("/user/{userName}/videos?fields=created_time,description,id,thumbnail_720_url,title", userName)
.retrieve()
.bodyToMono<DailymotionDetailsResult>()
.flatMapIterable { it.list }
.flatMap { image.fetchCoverUpdateInformationOrOption(it.cover).zipWith(it.toMono()) }
.map { (cover, item) ->
ItemFromUpdate(
url = URI("https://www.dailymotion.com/video/${item.id}"),
cover = cover.orNull(),
title = item.title,
pubDate = ZonedDateTime.ofInstant(Instant.ofEpochSecond(item.creationDate!!), ZoneId.of("Europe/Paris")),
description = item.description!!,
mimeType = "video/mp4"
)
}
val channelDetails = rc
.get()
.uri("/user/{userName}/videos?fields=created_time,description,id,thumbnail_720_url,title", userName)
.retrieve()
.body<DailymotionDetailsResult>()
?: return emptyList()

return channelDetails.list.map {
val cover = it.cover?.let(image::fetchCoverUpdateInformation)

ItemFromUpdate(
url = URI("https://www.dailymotion.com/video/${it.id}"),
cover = cover,
title = it.title,
pubDate = ZonedDateTime.ofInstant(Instant.ofEpochSecond(it.creationDate!!), ZoneId.of("Europe/Paris")),
description = it.description!!,
mimeType = "video/mp4"
)
}
}

override fun type() = Type("Dailymotion", "Dailymotion")
Expand All @@ -80,11 +93,11 @@ private val USER_NAME_EXTRACTOR = MatcherExtractor.from("^.+dailymotion.com/(.*)

private class DailymotionDetailsResult(val list: Set<DailymotionVideoDetail> = emptySet()) {
class DailymotionVideoDetail(
val id: String,
val title: String,
val description: String? = null,
@JsonProperty("created_time") val creationDate: Long? = null,
@JsonProperty("thumbnail_720_url") val cover: URI? = null
val id: String,
val title: String,
val description: String? = null,
@JsonProperty("created_time") val creationDate: Long? = null,
@JsonProperty("thumbnail_720_url") val cover: URI? = null
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
package com.github.davinkevin.podcastserver.update.updaters.dailymotion

import com.github.davinkevin.podcastserver.service.image.ImageServiceConfig
import com.github.davinkevin.podcastserver.service.image.ImageService
import com.github.davinkevin.podcastserver.service.image.ImageServiceConfig
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.client.RestClient

/**
* Created by kevin on 13/03/2020
*/
@Configuration
@Import(ImageServiceConfig::class)
class DailymotionUpdaterConfig {

@Bean
fun dailymotionUpdater(
wcb: WebClient.Builder,
image: ImageService
rcb: RestClient.Builder,
image: ImageService
): DailymotionUpdater {
val wc = wcb.clone().baseUrl("https://api.dailymotion.com").build()
val rc = rcb.clone().baseUrl("https://api.dailymotion.com").build()

return DailymotionUpdater(wc, image)
return DailymotionUpdater(rc, image)
}
}
Loading

0 comments on commit 1353981

Please sign in to comment.