complete publishing part

This commit is contained in:
InsanusMokrassar 2022-08-20 22:26:38 +06:00
parent 941505df42
commit c4e7f338a9
13 changed files with 146 additions and 9 deletions

View File

@ -17,6 +17,8 @@ kotlin {
}
jvmMain {
dependencies {
api libs.microutils.repos.exposed
api libs.plagubot.plugin
}
}
}

View File

@ -3,7 +3,7 @@
kotlin = "1.7.10"
kotlin-serialization = "1.4.0"
plagubot = "2.1.0"
plagubot = "2.1.1"
tgbotapi = "3.1.1"
microutils = "0.12.2"
kslog = "0.5.1"

View File

@ -2,5 +2,9 @@ package dev.inmo.plaguposter.posts.repo
import dev.inmo.micro_utils.repos.ReadCRUDRepo
import dev.inmo.plaguposter.posts.models.*
import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.MessageIdentifier
interface ReadPostsRepo : ReadCRUDRepo<RegisteredPost, PostId>
interface ReadPostsRepo : ReadCRUDRepo<RegisteredPost, PostId> {
suspend fun getIdByChatAndMessage(chatId: ChatId, messageId: MessageIdentifier): PostId?
}

View File

@ -2,6 +2,7 @@ package dev.inmo.plaguposter.posts.sending
import dev.inmo.kslog.common.logger
import dev.inmo.kslog.common.w
import dev.inmo.micro_utils.repos.deleteById
import dev.inmo.plaguposter.posts.models.PostId
import dev.inmo.plaguposter.posts.repo.PostsRepo
import dev.inmo.tgbotapi.bot.TelegramBot
@ -14,12 +15,13 @@ import dev.inmo.tgbotapi.types.message.content.MediaGroupContent
class PostPublisher(
private val bot: TelegramBot,
private val repo: PostsRepo,
private val postsRepo: PostsRepo,
private val cachingChatId: ChatId,
private val targetChatId: ChatId
private val targetChatId: ChatId,
private val deleteAfterPosting: Boolean = true
) {
suspend fun publish(postId: PostId) {
val messagesInfo = repo.getById(postId) ?: let {
val messagesInfo = postsRepo.getById(postId) ?: let {
logger.w { "Unable to get post with id $postId for publishing" }
return
}
@ -56,5 +58,9 @@ class PostPublisher(
}
}
if (deleteAfterPosting) {
postsRepo.deleteById(postId)
}
}
}

View File

@ -30,7 +30,7 @@ object Plugin : Plugin {
return
}
single { get<Json>().decodeFromJsonElement(Config.serializer(), configJson) }
single<PostsRepo> { ExposedPostsRepo(database, get()) }
single<PostsRepo> { ExposedPostsRepo(database) }
single {
val config = get<Config>()
PostPublisher(get(), get(), config.cacheChatId, config.targetChatId)

View File

@ -11,7 +11,7 @@ internal class ExposedContentInfoRepo(
override val database: Database,
postIdColumnReference: Column<String>
) : ExposedRepo, Table(name = "posts_content") {
val postIdColumn = (text("post_id") references postIdColumnReference).index()
val postIdColumn = text("post_id").references(postIdColumnReference, ReferenceOption.CASCADE, ReferenceOption.CASCADE)
val chatIdColumn = long("chat_id")
val messageIdColumn = long("message_id")
val groupColumn = text("group").nullable()

View File

@ -6,14 +6,16 @@ import dev.inmo.micro_utils.repos.exposed.AbstractExposedCRUDRepo
import dev.inmo.micro_utils.repos.exposed.initTable
import dev.inmo.plaguposter.posts.models.*
import dev.inmo.plaguposter.posts.repo.PostsRepo
import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.MessageIdentifier
import kotlinx.serialization.json.Json
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.statements.InsertStatement
import org.jetbrains.exposed.sql.statements.UpdateStatement
import org.jetbrains.exposed.sql.transactions.transaction
class ExposedPostsRepo(
override val database: Database,
json: Json
override val database: Database
) : PostsRepo, AbstractExposedCRUDRepo<RegisteredPost, PostId, NewPost>(
tableName = "posts"
) {
@ -88,4 +90,35 @@ class ExposedPostsRepo(
}
override fun insert(value: NewPost, it: InsertStatement<Number>) {}
override suspend fun deleteById(ids: List<PostId>) {
onBeforeDelete(ids)
transaction(db = database) {
val deleted = deleteWhere(null, null) {
selectByIds(ids)
}
with(contentRepo) {
deleteWhere {
postIdColumn.inList(ids.map { it.string })
}
}
if (deleted == ids.size) {
ids
} else {
ids.filter {
select { selectById(it) }.limit(1).none()
}
}
}.forEach {
_deletedObjectsIdsFlow.emit(it)
}
}
override suspend fun getIdByChatAndMessage(chatId: ChatId, messageId: MessageIdentifier): PostId? {
return transaction(database) {
with(contentRepo) {
select { chatIdColumn.eq(chatId.chatId).and(messageIdColumn.eq(messageId)) }.limit(1).firstOrNull() ?.get(postIdColumn)
} ?.let(::PostId)
}
}
}

View File

@ -10,6 +10,7 @@ dependencies {
api project(":plaguposter.posts")
api project(":plaguposter.posts_registrar")
api project(":plaguposter.triggers.command")
}
application {

View File

@ -4,6 +4,7 @@ String[] includes = [
":common",
":posts",
":posts_registrar",
":triggers:command",
":runner"
]

View File

@ -0,0 +1,22 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library"
}
apply from: "$mppProjectWithSerializationPresetPath"
kotlin {
sourceSets {
commonMain {
dependencies {
api project(":plaguposter.common")
api project(":plaguposter.posts")
}
}
jvmMain {
dependencies {
}
}
}
}

View File

@ -0,0 +1 @@
package dev.inmo.plaguposter.triggers.command

View File

@ -0,0 +1,66 @@
package dev.inmo.plaguposter.triggers.command
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.micro_utils.fsm.common.State
import dev.inmo.plagubot.Plugin
import dev.inmo.plaguposter.posts.repo.PostsRepo
import dev.inmo.plaguposter.posts.sending.PostPublisher
import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.api.send.send
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextWithFSM
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitTextMessage
import dev.inmo.tgbotapi.extensions.behaviour_builder.strictlyOn
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
import dev.inmo.tgbotapi.extensions.utils.botCommandTextSourceOrNull
import dev.inmo.tgbotapi.extensions.utils.contentMessageOrNull
import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.MessageIdentifier
import kotlinx.coroutines.flow.filter
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.*
import org.jetbrains.exposed.sql.Database
import org.koin.core.Koin
import org.koin.core.module.Module
object Plugin : Plugin {
@Serializable
private data class PublishState(
override val context: ChatId,
val sourceMessageId: MessageIdentifier,
val messageInReply: MessageIdentifier
) : State
override fun Module.setupDI(database: Database, params: JsonObject) {
}
override suspend fun BehaviourContextWithFSM<State>.setupBotPlugin(koin: Koin) {
val postsRepo = koin.get<PostsRepo>()
val publisher = koin.get<PostPublisher>()
strictlyOn { state: PublishState ->
null
}
onCommand("publish_post") {
val messageInReply = it.replyTo ?.contentMessageOrNull() ?: let { _ ->
reply(it, "You should reply some message of post to trigger it for posting")
return@onCommand
}
val postId = postsRepo.getIdByChatAndMessage(messageInReply.chat.id, messageInReply.messageId)
if (postId == null) {
reply(
it,
"Unable to find any post related to the message in reply"
)
return@onCommand
}
publisher.publish(postId)
reply(
it,
"Successfully triggered publishing"
)
}
}
}

View File

@ -0,0 +1 @@
<manifest package="dev.inmo.plaguposter.triggers.command"/>