PlaguPoster/posts/src/jvmMain/kotlin/exposed/ExposedPostsRepo.kt

161 lines
5.6 KiB
Kotlin
Raw Normal View History

2022-08-18 12:59:05 +00:00
package dev.inmo.plaguposter.posts.exposed
import com.benasher44.uuid.uuid4
2022-09-09 11:27:11 +00:00
import com.soywiz.klock.DateTime
2022-08-18 12:59:05 +00:00
import dev.inmo.micro_utils.repos.KeyValuesRepo
2022-10-25 07:02:19 +00:00
import dev.inmo.micro_utils.repos.UpdatedValuePair
2022-08-18 12:59:05 +00:00
import dev.inmo.micro_utils.repos.exposed.AbstractExposedCRUDRepo
2022-08-19 18:52:31 +00:00
import dev.inmo.micro_utils.repos.exposed.initTable
2022-08-18 12:59:05 +00:00
import dev.inmo.plaguposter.posts.models.*
import dev.inmo.plaguposter.posts.repo.PostsRepo
2022-08-20 16:26:38 +00:00
import dev.inmo.tgbotapi.types.ChatId
2022-11-17 09:09:10 +00:00
import dev.inmo.tgbotapi.types.IdChatIdentifier
2022-08-20 16:26:38 +00:00
import dev.inmo.tgbotapi.types.MessageIdentifier
2022-09-04 09:46:45 +00:00
import kotlinx.coroutines.flow.*
2022-08-18 12:59:05 +00:00
import kotlinx.serialization.json.Json
import org.jetbrains.exposed.sql.*
2022-11-17 09:09:10 +00:00
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.SqlExpressionBuilder.inList
2022-10-25 06:43:12 +00:00
import org.jetbrains.exposed.sql.statements.*
2022-08-20 16:26:38 +00:00
import org.jetbrains.exposed.sql.transactions.transaction
2022-08-18 12:59:05 +00:00
class ExposedPostsRepo(
2022-08-20 16:26:38 +00:00
override val database: Database
2022-08-18 12:59:05 +00:00
) : PostsRepo, AbstractExposedCRUDRepo<RegisteredPost, PostId, NewPost>(
tableName = "posts"
) {
2022-10-25 06:43:12 +00:00
val idColumn = text("id")
2022-09-09 12:01:50 +00:00
val createdColumn = double("datetime").default(0.0)
2022-08-18 12:59:05 +00:00
private val contentRepo by lazy {
ExposedContentInfoRepo(
database,
idColumn
)
}
2022-08-19 18:52:31 +00:00
override val primaryKey: PrimaryKey = PrimaryKey(idColumn)
2022-08-18 12:59:05 +00:00
2022-11-17 09:09:10 +00:00
override val selectById: ISqlExpressionBuilder.(PostId) -> Op<Boolean> = { idColumn.eq(it.string) }
override val selectByIds: ISqlExpressionBuilder.(List<PostId>) -> Op<Boolean> = { idColumn.inList(it.map { it.string }) }
2022-08-18 12:59:05 +00:00
override val ResultRow.asObject: RegisteredPost
get() {
val id = PostId(get(idColumn))
return RegisteredPost(
id,
2022-09-09 11:27:11 +00:00
DateTime(get(createdColumn)),
2022-08-18 12:59:05 +00:00
with(contentRepo) {
select { postIdColumn.eq(id.string) }.map {
it.asObject
}
}
)
}
2022-09-04 09:46:45 +00:00
private val _removedPostsFlow = MutableSharedFlow<RegisteredPost>()
override val removedPostsFlow: Flow<RegisteredPost> = _removedPostsFlow.asSharedFlow()
2022-08-19 18:52:31 +00:00
init {
initTable()
}
2022-08-18 12:59:05 +00:00
override fun InsertStatement<Number>.asObject(value: NewPost): RegisteredPost {
val id = PostId(get(idColumn))
return RegisteredPost(
id,
2022-09-09 11:27:11 +00:00
DateTime(get(createdColumn)),
2022-08-18 12:59:05 +00:00
with(contentRepo) {
select { postIdColumn.eq(id.string) }.map {
it.asObject
}
}
)
}
2022-10-25 06:43:12 +00:00
override fun createAndInsertId(value: NewPost, it: InsertStatement<Number>): PostId {
val id = PostId(uuid4().toString())
it[idColumn] = id.string
return id
}
2022-10-25 07:02:19 +00:00
override fun update(id: PostId?, value: NewPost, it: UpdateBuilder<Int>) {}
private fun updateContent(post: RegisteredPost) {
transaction(database) {
with(contentRepo) {
deleteWhere { postIdColumn.eq(post.id.string) }
post.content.forEach { contentInfo ->
insert {
it[postIdColumn] = post.id.string
it[chatIdColumn] = contentInfo.chatId.chatId
2022-11-17 09:09:10 +00:00
it[threadIdColumn] = contentInfo.chatId.threadId
2022-10-25 07:02:19 +00:00
it[messageIdColumn] = contentInfo.messageId
it[groupColumn] = contentInfo.group
it[orderColumn] = contentInfo.order
}
2022-08-18 12:59:05 +00:00
}
}
}
}
2022-09-09 12:17:02 +00:00
override fun insert(value: NewPost, it: InsertStatement<Number>) {
2022-10-25 06:43:12 +00:00
super.insert(value, it)
2022-09-09 12:17:02 +00:00
it[createdColumn] = DateTime.now().unixMillis
}
2022-08-20 16:26:38 +00:00
2022-10-25 07:02:19 +00:00
override suspend fun onAfterCreate(values: List<Pair<NewPost, RegisteredPost>>): List<RegisteredPost> {
values.forEach {
2022-11-17 09:09:10 +00:00
updateContent(it.second.copy(content = it.first.content))
2022-10-25 07:02:19 +00:00
}
return super.onAfterCreate(values)
}
override suspend fun onAfterUpdate(value: List<UpdatedValuePair<NewPost, RegisteredPost>>): List<RegisteredPost> {
value.forEach {
2022-11-17 09:09:10 +00:00
updateContent(it.second.copy(content = it.first.content))
2022-10-25 07:02:19 +00:00
}
return super.onAfterUpdate(value)
}
2022-08-20 16:26:38 +00:00
override suspend fun deleteById(ids: List<PostId>) {
onBeforeDelete(ids)
2022-09-04 09:46:45 +00:00
val posts = ids.mapNotNull {
getById(it)
}.associateBy { it.id }
val existsIds = posts.keys.toList()
2022-08-20 16:26:38 +00:00
transaction(db = database) {
val deleted = deleteWhere(null, null) {
2022-11-17 09:09:10 +00:00
selectByIds(it, existsIds)
2022-08-20 16:26:38 +00:00
}
with(contentRepo) {
deleteWhere {
2022-09-04 09:46:45 +00:00
postIdColumn.inList(existsIds.map { it.string })
2022-08-20 16:26:38 +00:00
}
}
2022-09-04 09:46:45 +00:00
if (deleted == existsIds.size) {
existsIds
2022-08-20 16:26:38 +00:00
} else {
2022-09-04 09:46:45 +00:00
existsIds.filter {
2022-08-20 16:26:38 +00:00
select { selectById(it) }.limit(1).none()
}
}
}.forEach {
_deletedObjectsIdsFlow.emit(it)
2022-09-04 09:46:45 +00:00
_removedPostsFlow.emit(posts[it] ?: return@forEach)
2022-08-20 16:26:38 +00:00
}
}
2022-11-17 09:09:10 +00:00
override suspend fun getIdByChatAndMessage(chatId: IdChatIdentifier, messageId: MessageIdentifier): PostId? {
2022-08-20 16:26:38 +00:00
return transaction(database) {
with(contentRepo) {
2022-11-17 09:09:10 +00:00
select { chatIdColumn.eq(chatId.chatId).and(threadIdColumn.eq(chatId.threadId)).and(messageIdColumn.eq(messageId)) }.limit(1).firstOrNull() ?.get(postIdColumn)
2022-08-20 16:26:38 +00:00
} ?.let(::PostId)
}
}
2022-09-09 11:27:11 +00:00
override suspend fun getPostCreationTime(postId: PostId): DateTime? = transaction(database) {
select { selectById(postId) }.limit(1).firstOrNull() ?.get(createdColumn) ?.let(::DateTime)
}
2022-08-18 12:59:05 +00:00
}