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

114 lines
4.3 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.client.tempUpload
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.common.common.FileBasedInputProvider
import dev.inmo.postssystem.features.common.common.SimpleInputProvider
import dev.inmo.postssystem.features.content.common.*
import dev.inmo.postssystem.features.files.common.FileId
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.*
import kotlinx.serialization.modules.polymorphic
class ClientWritePostsService(
private val baseUrl: String,
unifiedRequester: UnifiedRequester
) : WritePostsService {
private val root = buildStandardUrl(baseUrl, postsRootPath)
private val unifiedRequester = UnifiedRequester(
unifiedRequester.client,
unifiedRequester.serialFormat.createWithSerializerModuleExtension {
polymorphic(Content::class) {
subclass(BinaryContent::class, BinaryContentSerializer(TempFileIdentifierInputProvider::class, TempFileIdentifierInputProvider.serializer()))
}
}
)
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
)
private val tempUploadFullPath = buildStandardUrl(
root,
postsCreateTempPathPart
)
private suspend fun prepareContent(content: Content): Content? {
return (content as? BinaryContent) ?.let {
when (val provider = it.inputProvider) {
is FileBasedInputProvider -> {
val fileId = unifiedRequester.tempUpload(
tempUploadFullPath,
provider.file
)
println(fileId)
it.copy(inputProvider = TempFileIdentifierInputProvider(FileId(fileId.string)))
}
is TempFileIdentifierInputProvider -> it
else -> return@prepareContent null
}
} ?: content
}
override suspend fun create(newPost: FullNewPost): RegisteredPost? {
val mappedContent = newPost.content.mapNotNull {
prepareContent(it)
}
val mappedPost = newPost.copy(
content = mappedContent
)
return unifiedRequester.unipost(
createFullPath,
contentsSerializer to mappedPost.content,
RegisteredPost.serializer().nullable
)
}
override suspend fun update(
postId: PostId,
content: List<Either<ContentId, Content>>
): RegisteredPost? {
val mappedContent = content.mapNotNull {
it.mapOnSecond { content ->
prepareContent(content) ?.either() ?: return@mapNotNull null
} ?: it
}
return unifiedRequester.unipost(
buildStandardUrl(
root,
updateRouting,
postsPostIdParameter to unifiedRequester.encodeUrlQueryValue(PostId.serializer(), postId)
),
contentsEitherSerializer to mappedContent,
RegisteredPost.serializer().nullable
)
}
override suspend fun remove(postId: PostId) = unifiedRequester.unipost(
removeFullPath,
PostId.serializer() to postId,
Unit.serializer()
)
}