add neko integration

improve build.gradle.kts
This commit is contained in:
Denis Savosin
2024-10-24 12:49:44 +07:00
parent 70caf2da91
commit 511116f8bb
12 changed files with 295 additions and 10 deletions

View File

@@ -17,6 +17,8 @@ import com.github.dannecron.demo.services.database.product.ProductServiceImpl
import com.github.dannecron.demo.services.kafka.Producer
import com.github.dannecron.demo.services.validation.SchemaValidator
import com.github.dannecron.demo.services.validation.SchemaValidatorImp
import io.ktor.client.engine.*
import io.ktor.client.engine.cio.*
import io.micrometer.observation.ObservationRegistry
import io.micrometer.observation.aop.ObservedAspect
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter
@@ -25,6 +27,8 @@ import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import com.github.dannecron.demo.services.neko.Client as NekoClient
import com.github.dannecron.demo.services.neko.ClientImpl as NekoClientImpl
@Configuration
@EnableConfigurationProperties(KafkaProperties::class, ValidationProperties::class)
@@ -68,5 +72,17 @@ class AppConfig(
@Bean
fun observedAspect(@Autowired observationRegistry: ObservationRegistry) = ObservedAspect(observationRegistry)
@Bean
fun httpClientEngine(): HttpClientEngine = CIO.create()
@Bean
fun nekoClient(
@Autowired httpClientEngine: HttpClientEngine,
@Value("\${neko.baseUrl}") baseUrl: String,
): NekoClient = NekoClientImpl(
engine = httpClientEngine,
baseUrl = baseUrl,
)
}

View File

@@ -0,0 +1,14 @@
package com.github.dannecron.demo.services.neko
import com.github.dannecron.demo.services.neko.dto.ImagesResponse
import com.github.dannecron.demo.services.neko.exceptions.RequestException
import org.springframework.stereotype.Service
@Service
interface Client {
@Throws(RequestException::class)
fun getCategories(): Set<String>
@Throws(RequestException::class)
fun getImages(category: String, amount: Int): ImagesResponse
}

View File

@@ -0,0 +1,46 @@
package com.github.dannecron.demo.services.neko
import com.github.dannecron.demo.services.neko.dto.CategoryFormat
import com.github.dannecron.demo.services.neko.dto.ImagesResponse
import com.github.dannecron.demo.services.neko.exceptions.RequestException
import io.ktor.client.*
import io.ktor.client.engine.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.json.Json
class ClientImpl(
engine: HttpClientEngine,
private val baseUrl: String,
): Client {
private val httpClient = HttpClient(engine)
override fun getCategories() = runBlocking {
httpClient.get(urlString = baseUrl) {
url {
path("/api/v2/endpoints")
}
}
.takeIf { it.status.value in 200..209 }
?.let {
response -> Json.decodeFromString<Map<String, CategoryFormat>>(response.bodyAsText()).keys
}
?: throw RequestException("get categories error")
}
override fun getImages(category: String, amount: Int) = runBlocking {
httpClient.get(urlString = baseUrl) {
url {
path("/api/v2/$category")
parameters.append("amount", amount.toString())
}
}
.takeIf { it.status.value in 200..209 }
?.let {
response -> Json.decodeFromString<ImagesResponse>(response.bodyAsText())
}
?: throw RequestException("get images error")
}
}

View File

@@ -0,0 +1,8 @@
package com.github.dannecron.demo.services.neko.dto
import kotlinx.serialization.Serializable
@Serializable
data class CategoryFormat(
val format: String,
)

View File

@@ -0,0 +1,17 @@
package com.github.dannecron.demo.services.neko.dto
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class Image(
val url: String,
@SerialName("anime_name")
val animeName: String? = null,
@SerialName("artist_href")
val artistHref: String? = null,
@SerialName("artist_name")
val artistName: String? = null,
@SerialName("source_url")
val sourceUrl: String? = null,
)

View File

@@ -0,0 +1,8 @@
package com.github.dannecron.demo.services.neko.dto
import kotlinx.serialization.Serializable
@Serializable
data class ImagesResponse(
val results: List<Image>
)

View File

@@ -0,0 +1,3 @@
package com.github.dannecron.demo.services.neko.exceptions
class RequestException(message: String): RuntimeException(message)

View File

@@ -7,3 +7,8 @@ fun Double.roundTo(numFractionDigits: Int): Double {
val factor = 10.0.pow(numFractionDigits.toDouble())
return (this * factor).roundToInt() / factor
}
fun String.snakeToCamelCase(): String {
val pattern = "_[a-z]".toRegex()
return replace(pattern) { it.value.last().uppercase() }
}