core/services/posts/client/src/commonMain/kotlin/dev/inmo/postssystem/services/posts/client/ClientWritePostsService.kt

124 lines
5.2 KiB
Kotlin

package dev.inmo.postssystem.services.posts.client
import dev.inmo.micro_utils.common.*
import dev.inmo.micro_utils.ktor.client.UnifiedRequester
import dev.inmo.micro_utils.ktor.common.buildStandardUrl
import dev.inmo.micro_utils.ktor.common.encodeHex
import dev.inmo.micro_utils.repos.ktor.common.crud.createRouting
import dev.inmo.micro_utils.repos.ktor.common.crud.updateRouting
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.removeRoute
import dev.inmo.postssystem.features.content.common.*
import dev.inmo.postssystem.features.posts.common.PostId
import dev.inmo.postssystem.features.posts.common.RegisteredPost
import dev.inmo.postssystem.services.posts.common.*
import io.ktor.client.request.forms.InputProvider
import io.ktor.client.request.forms.formData
import io.ktor.client.request.headers
import io.ktor.client.request.post
import io.ktor.http.HttpHeaders
import kotlinx.serialization.builtins.*
class ClientWritePostsService(
private val baseUrl: String,
private val unifiedRequester: UnifiedRequester
) : WritePostsService {
private val root = buildStandardUrl(baseUrl, postsRootPath)
private val contentEitherSerializer = EitherSerializer(ContentId.serializer(), ContentSerializer)
private val contentsEitherSerializer = ListSerializer(contentEitherSerializer)
private val contentsSerializer = ListSerializer(ContentSerializer)
private val createFullPath = buildStandardUrl(
root,
createRouting
)
private val removeFullPath = buildStandardUrl(
root,
removeRoute
)
override suspend fun create(newPost: FullNewPost): RegisteredPost? {
return if (newPost.content.any { it is BinaryContent }) {
val answer = unifiedRequester.client.post<ByteArray>(createFullPath) {
formData {
newPost.content.forEachIndexed { i, content ->
when (content) {
is BinaryContent -> append(
i.toString(),
InputProvider(block = content.inputProvider::invoke),
headers {
append(HttpHeaders.ContentType, content.mimeType.raw)
append(HttpHeaders.ContentDisposition, "filename=\"${content.filename.name}\"")
}.build()
)
else -> append(
i.toString(),
unifiedRequester.serialFormat.encodeHex(ContentSerializer, content)
)
}
}
}
}
unifiedRequester.serialFormat.decodeFromByteArray(RegisteredPost.serializer().nullable, answer)
} else {
unifiedRequester.unipost(
createFullPath,
contentsSerializer to newPost.content,
RegisteredPost.serializer().nullable
)
}
}
override suspend fun update(
postId: PostId,
content: List<Either<ContentId, Content>>
): RegisteredPost? {
return if (content.any { it.optionalT2.data is BinaryContent }) {
val answer = unifiedRequester.client.post<ByteArray>(createFullPath) {
formData {
content.forEachIndexed { i, eitherContent ->
eitherContent.onFirst {
append(
i.toString(),
unifiedRequester.serialFormat.encodeHex(contentEitherSerializer, it.either())
)
}.onSecond {
when (it) {
is BinaryContent -> append(
i.toString(),
InputProvider(block = it.inputProvider::invoke),
headers {
append(HttpHeaders.ContentType, it.mimeType.raw)
append(HttpHeaders.ContentDisposition, "filename=\"${it.filename.name}\"")
}.build()
)
else -> append(
i.toString(),
unifiedRequester.serialFormat.encodeHex(contentEitherSerializer, it.either())
)
}
}
}
}
}
unifiedRequester.serialFormat.decodeFromByteArray(RegisteredPost.serializer().nullable, answer)
} else {
unifiedRequester.unipost(
buildStandardUrl(
root,
updateRouting,
postsPostIdParameter to unifiedRequester.encodeUrlQueryValue(PostId.serializer(), postId)
),
contentsEitherSerializer to content,
RegisteredPost.serializer().nullable
)
}
}
override suspend fun remove(postId: PostId) = unifiedRequester.unipost(
removeFullPath,
PostId.serializer() to postId,
Unit.serializer()
)
}