mirror of
https://github.com/InsanusMokrassar/PlaguPoster.git
synced 2024-12-22 14:07:14 +00:00
add timers repo and timers handler
This commit is contained in:
parent
9403b133f9
commit
c632a2ba14
@ -4,8 +4,11 @@ import com.soywiz.klock.DateTime
|
||||
import com.soywiz.klock.DateTimeTz
|
||||
import com.soywiz.klock.Month
|
||||
import com.soywiz.klock.Year
|
||||
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
||||
import dev.inmo.plaguposter.common.SuccessfulSymbol
|
||||
import dev.inmo.plaguposter.posts.models.Post
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.tgbotapi.extensions.api.answers.answer
|
||||
import dev.inmo.tgbotapi.extensions.api.edit.edit
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onMessageDataCallbackQuery
|
||||
@ -38,7 +41,9 @@ object ButtonsBuilder {
|
||||
dataButton(SuccessfulSymbol, "$changeDateDataPrefix $postId $unixMillis")
|
||||
}
|
||||
|
||||
suspend fun BehaviourContext.includeKeyboardHandling() {
|
||||
suspend fun BehaviourContext.includeKeyboardHandling(
|
||||
onSavePublishingTime: suspend (PostId, DateTime) -> Boolean
|
||||
) {
|
||||
fun buildKeyboard(
|
||||
prefix: String,
|
||||
postId: PostId,
|
||||
@ -180,5 +185,21 @@ object ButtonsBuilder {
|
||||
oldDateTime.offset
|
||||
)
|
||||
}
|
||||
|
||||
onMessageDataCallbackQuery(Regex("$changeDateDataPrefix .*")) {
|
||||
val (_, rawPostId, rawDateTimeMillis) = it.data.split(" ")
|
||||
val currentMillis = rawDateTimeMillis.toLongOrNull() ?: return@onMessageDataCallbackQuery
|
||||
val currentDateTime = DateTime(currentMillis)
|
||||
val postId = PostId(rawPostId)
|
||||
|
||||
val success = runCatchingSafely {
|
||||
onSavePublishingTime(postId, currentDateTime)
|
||||
}.getOrElse { false }
|
||||
|
||||
answer(
|
||||
it,
|
||||
if (success) "Successfully set timer" else "Unable to set timer"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
57
triggers/timer/src/commonMain/kotlin/TimersHandler.kt
Normal file
57
triggers/timer/src/commonMain/kotlin/TimersHandler.kt
Normal file
@ -0,0 +1,57 @@
|
||||
package dev.inmo.plaguposter.triggers.timer
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
|
||||
import dev.inmo.micro_utils.coroutines.plus
|
||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||
import dev.inmo.micro_utils.repos.unset
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.plaguposter.posts.sending.PostPublisher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
|
||||
class TimersHandler(
|
||||
private val timersRepo: TimersRepo,
|
||||
private val publisher: PostPublisher,
|
||||
private val scope: CoroutineScope
|
||||
) {
|
||||
private var currentPostAndJob: Pair<PostId, Job>? = null
|
||||
private val currentJobMutex = Mutex()
|
||||
|
||||
init {
|
||||
(flowOf(Unit) + timersRepo.onNewValue + timersRepo.onValueRemoved).subscribeSafelyWithoutExceptions(scope) {
|
||||
refreshPublishingJob()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun refreshPublishingJob() {
|
||||
val minimal = timersRepo.getMinimalDateTimePost()
|
||||
|
||||
currentJobMutex.withLock {
|
||||
if (minimal ?.first == currentPostAndJob ?.first) {
|
||||
return@withLock
|
||||
}
|
||||
|
||||
currentPostAndJob ?.second ?.cancel()
|
||||
|
||||
currentPostAndJob = minimal ?.let { (postId, dateTime) ->
|
||||
postId to scope.launchSafelyWithoutExceptions {
|
||||
val now = DateTime.now()
|
||||
val span = dateTime - now
|
||||
|
||||
delay(span.millisecondsLong)
|
||||
|
||||
publisher.publish(postId)
|
||||
|
||||
timersRepo.unset(postId)
|
||||
|
||||
refreshPublishingJob()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
9
triggers/timer/src/commonMain/kotlin/TimersRepo.kt
Normal file
9
triggers/timer/src/commonMain/kotlin/TimersRepo.kt
Normal file
@ -0,0 +1,9 @@
|
||||
package dev.inmo.plaguposter.triggers.timer
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
|
||||
interface TimersRepo : KeyValueRepo<PostId, DateTime> {
|
||||
suspend fun getMinimalDateTimePost(): Pair<PostId, DateTime>?
|
||||
}
|
@ -2,8 +2,10 @@ package dev.inmo.plaguposter.triggers.timer
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
||||
import dev.inmo.micro_utils.repos.set
|
||||
import dev.inmo.plagubot.Plugin
|
||||
import dev.inmo.plaguposter.posts.repo.ReadPostsRepo
|
||||
import dev.inmo.plaguposter.triggers.timer.repo.ExposedTimersRepo
|
||||
import dev.inmo.tgbotapi.extensions.api.edit.edit
|
||||
import dev.inmo.tgbotapi.extensions.api.send.send
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
@ -12,15 +14,22 @@ import kotlinx.serialization.json.*
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.koin.core.Koin
|
||||
import org.koin.core.module.Module
|
||||
import org.koin.dsl.binds
|
||||
|
||||
object Plugin : Plugin {
|
||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
||||
single { ExposedTimersRepo(get(), get(), get()) } binds arrayOf(TimersRepo::class)
|
||||
single(createdAtStart = true) { TimersHandler(get(), get(), get()) }
|
||||
}
|
||||
|
||||
override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) {
|
||||
val postsRepo = koin.get<ReadPostsRepo>()
|
||||
val timersRepo = koin.get<TimersRepo>()
|
||||
with(ButtonsBuilder) {
|
||||
includeKeyboardHandling()
|
||||
includeKeyboardHandling { postId, dateTime ->
|
||||
timersRepo.set(postId, dateTime)
|
||||
true
|
||||
}
|
||||
}
|
||||
onCommand("test") {
|
||||
val reply = it.replyTo ?: return@onCommand
|
||||
|
62
triggers/timer/src/jvmMain/kotlin/repo/ExposedTimersRepo.kt
Normal file
62
triggers/timer/src/jvmMain/kotlin/repo/ExposedTimersRepo.kt
Normal file
@ -0,0 +1,62 @@
|
||||
package dev.inmo.plaguposter.triggers.timer.repo
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import dev.inmo.micro_utils.common.firstNotNull
|
||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||
import dev.inmo.micro_utils.pagination.paginate
|
||||
import dev.inmo.micro_utils.repos.exposed.initTable
|
||||
import dev.inmo.micro_utils.repos.exposed.keyvalue.AbstractExposedKeyValueRepo
|
||||
import dev.inmo.micro_utils.repos.unset
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||
import dev.inmo.plaguposter.triggers.timer.TimersRepo
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import org.jetbrains.exposed.sql.Column
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.jetbrains.exposed.sql.ISqlExpressionBuilder
|
||||
import org.jetbrains.exposed.sql.Op
|
||||
import org.jetbrains.exposed.sql.ResultRow
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.statements.InsertStatement
|
||||
import org.jetbrains.exposed.sql.statements.UpdateBuilder
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
|
||||
class ExposedTimersRepo(
|
||||
database: Database,
|
||||
postsRepo: PostsRepo,
|
||||
scope: CoroutineScope
|
||||
) : TimersRepo, AbstractExposedKeyValueRepo<PostId, DateTime>(
|
||||
database,
|
||||
"timers"
|
||||
) {
|
||||
override val keyColumn = text("post_id")
|
||||
private val dateTimeColumn = long("date_time")
|
||||
override val selectById: ISqlExpressionBuilder.(PostId) -> Op<Boolean> = { keyColumn.eq(it.string) }
|
||||
override val selectByValue: ISqlExpressionBuilder.(DateTime) -> Op<Boolean> = { dateTimeColumn.eq(it.unixMillisLong) }
|
||||
override val ResultRow.asKey: PostId
|
||||
get() = PostId(get(keyColumn))
|
||||
override val ResultRow.asObject: DateTime
|
||||
get() = DateTime(get(dateTimeColumn))
|
||||
|
||||
val postsRepoListeningJob = postsRepo.deletedObjectsIdsFlow.subscribeSafelyWithoutExceptions(scope) {
|
||||
unset(it)
|
||||
}
|
||||
|
||||
init {
|
||||
initTable()
|
||||
}
|
||||
|
||||
override fun update(k: PostId, v: DateTime, it: UpdateBuilder<Int>) {
|
||||
it[dateTimeColumn] = v.unixMillisLong
|
||||
}
|
||||
|
||||
override fun insertKey(k: PostId, v: DateTime, it: InsertStatement<Number>) {
|
||||
it[keyColumn] = k.string
|
||||
}
|
||||
|
||||
override suspend fun getMinimalDateTimePost(): Pair<PostId, DateTime>? = transaction(database) {
|
||||
selectAll().orderBy(dateTimeColumn).limit(1).firstOrNull() ?.let {
|
||||
PostId(it[keyColumn]) to DateTime(it[dateTimeColumn])
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user