This commit is contained in:
InsanusMokrassar 2022-09-09 17:27:11 +06:00
parent 53675ca598
commit 6d8bc0326f
13 changed files with 126 additions and 5 deletions

View File

@ -0,0 +1,7 @@
package dev.inmo.plaguposter.common
import com.soywiz.klock.DateTime
import kotlinx.serialization.Serializer
@Serializer(DateTime::class)
object DateTimeSerializer

View File

@ -4,8 +4,8 @@ kotlin = "1.7.10"
kotlin-serialization = "1.4.0" kotlin-serialization = "1.4.0"
plagubot = "2.3.0" plagubot = "2.3.0"
tgbotapi = "3.2.0" tgbotapi = "3.2.1"
microutils = "0.12.6" microutils = "0.12.11"
kslog = "0.5.1" kslog = "0.5.1"
krontab = "0.8.0" krontab = "0.8.0"

View File

@ -1,5 +1,7 @@
package dev.inmo.plaguposter.posts.models package dev.inmo.plaguposter.posts.models
import com.soywiz.klock.DateTime
import dev.inmo.plaguposter.common.DateTimeSerializer
import dev.inmo.tgbotapi.types.ChatId import dev.inmo.tgbotapi.types.ChatId
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -16,5 +18,7 @@ data class NewPost(
@Serializable @Serializable
data class RegisteredPost( data class RegisteredPost(
val id: PostId, val id: PostId,
@Serializable(DateTimeSerializer::class)
val created: DateTime,
override val content: List<PostContentInfo> override val content: List<PostContentInfo>
) : Post ) : Post

View File

@ -1,5 +1,6 @@
package dev.inmo.plaguposter.posts.repo package dev.inmo.plaguposter.posts.repo
import com.soywiz.klock.DateTime
import dev.inmo.micro_utils.repos.ReadCRUDRepo import dev.inmo.micro_utils.repos.ReadCRUDRepo
import dev.inmo.plaguposter.posts.models.* import dev.inmo.plaguposter.posts.models.*
import dev.inmo.tgbotapi.types.ChatId import dev.inmo.tgbotapi.types.ChatId
@ -7,4 +8,5 @@ import dev.inmo.tgbotapi.types.MessageIdentifier
interface ReadPostsRepo : ReadCRUDRepo<RegisteredPost, PostId> { interface ReadPostsRepo : ReadCRUDRepo<RegisteredPost, PostId> {
suspend fun getIdByChatAndMessage(chatId: ChatId, messageId: MessageIdentifier): PostId? suspend fun getIdByChatAndMessage(chatId: ChatId, messageId: MessageIdentifier): PostId?
suspend fun getPostCreationTime(postId: PostId): DateTime?
} }

View File

@ -1,6 +1,7 @@
package dev.inmo.plaguposter.posts.exposed package dev.inmo.plaguposter.posts.exposed
import com.benasher44.uuid.uuid4 import com.benasher44.uuid.uuid4
import com.soywiz.klock.DateTime
import dev.inmo.micro_utils.repos.KeyValuesRepo import dev.inmo.micro_utils.repos.KeyValuesRepo
import dev.inmo.micro_utils.repos.exposed.AbstractExposedCRUDRepo import dev.inmo.micro_utils.repos.exposed.AbstractExposedCRUDRepo
import dev.inmo.micro_utils.repos.exposed.initTable import dev.inmo.micro_utils.repos.exposed.initTable
@ -21,6 +22,9 @@ class ExposedPostsRepo(
tableName = "posts" tableName = "posts"
) { ) {
val idColumn = text("id").clientDefault { uuid4().toString() } val idColumn = text("id").clientDefault { uuid4().toString() }
val createdColumn = double("datetime").default(0.0).clientDefault {
DateTime.nowUnix()
}
private val contentRepo by lazy { private val contentRepo by lazy {
ExposedContentInfoRepo( ExposedContentInfoRepo(
@ -38,6 +42,7 @@ class ExposedPostsRepo(
val id = PostId(get(idColumn)) val id = PostId(get(idColumn))
return RegisteredPost( return RegisteredPost(
id, id,
DateTime(get(createdColumn)),
with(contentRepo) { with(contentRepo) {
select { postIdColumn.eq(id.string) }.map { select { postIdColumn.eq(id.string) }.map {
it.asObject it.asObject
@ -70,6 +75,7 @@ class ExposedPostsRepo(
return RegisteredPost( return RegisteredPost(
id, id,
DateTime(get(createdColumn)),
with(contentRepo) { with(contentRepo) {
select { postIdColumn.eq(id.string) }.map { select { postIdColumn.eq(id.string) }.map {
it.asObject it.asObject
@ -130,4 +136,8 @@ class ExposedPostsRepo(
} ?.let(::PostId) } ?.let(::PostId)
} }
} }
override suspend fun getPostCreationTime(postId: PostId): DateTime? = transaction(database) {
select { selectById(postId) }.limit(1).firstOrNull() ?.get(createdColumn) ?.let(::DateTime)
}
} }

23
ratings/gc/build.gradle Normal file
View File

@ -0,0 +1,23 @@
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.ratings")
api libs.krontab
}
}
jvmMain {
dependencies {
}
}
}
}

View File

@ -0,0 +1 @@
package dev.inmo.plaguposter.ratings.gc

View File

@ -0,0 +1,62 @@
package dev.inmo.plaguposter.ratings.gc
import com.soywiz.klock.milliseconds
import com.soywiz.klock.seconds
import dev.inmo.krontab.KrontabTemplate
import dev.inmo.krontab.toSchedule
import dev.inmo.krontab.utils.asFlow
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.micro_utils.repos.deleteById
import dev.inmo.micro_utils.repos.id
import dev.inmo.plagubot.Plugin
import dev.inmo.plaguposter.posts.repo.PostsRepo
import dev.inmo.plaguposter.ratings.models.Rating
import dev.inmo.plaguposter.ratings.repo.RatingsRepo
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
import dev.inmo.tgbotapi.types.MilliSeconds
import dev.inmo.tgbotapi.types.Seconds
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
internal data class Config(
val autoclear: AutoClearOptions? = null,
val immediateDrop: Rating? = null,
) {
@Serializable
data class AutoClearOptions(
val rating: Rating,
val autoClearKrontab: KrontabTemplate,
val skipPostAge: Seconds? = null
)
}
override fun Module.setupDI(database: Database, params: JsonObject) {
single { get<Json>().decodeFromJsonElement(Config.serializer(), params["gc"] ?: return@single null) }
}
override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) {
val ratingsRepo = koin.get<RatingsRepo>()
val postsRepo = koin.get<PostsRepo>()
val config = koin.get<Config>()
config.immediateDrop ?.let { toDrop ->
ratingsRepo.onNewValue.subscribeSafelyWithoutExceptions(this) {
postsRepo.deleteById(it.id)
}
}
config.autoclear ?.let { autoclear ->
autoclear.autoClearKrontab.toSchedule().asFlow().subscribeSafelyWithoutExceptions(scope) {
val dropCreatedBefore = it - (autoclear.skipPostAge ?: 0).seconds
ratingsRepo.getPostsWithRatingLessEq(autoclear.rating).keys.forEach {
if ((postsRepo.getPostCreationTime(it) ?: return@forEach) < dropCreatedBefore) {
postsRepo.deleteById(it)
}
}
}
}
}
}

View File

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

View File

@ -17,7 +17,8 @@ import kotlin.random.Random
data class RatingConfig( data class RatingConfig(
val min: Rating?, val min: Rating?,
val max: Rating?, val max: Rating?,
val prefer: Prefer val prefer: Prefer,
val otherwise: RatingConfig? = null
) { ) {
suspend fun select(repo: RatingsRepo, exclude: List<PostId>): PostId? { suspend fun select(repo: RatingsRepo, exclude: List<PostId>): PostId? {
var reversed: Boolean = false var reversed: Boolean = false
@ -70,7 +71,7 @@ data class RatingConfig(
Prefer.Max, Prefer.Max,
Prefer.Min -> posts.firstOrNull() Prefer.Min -> posts.firstOrNull()
Prefer.Random -> posts.randomOrNull() Prefer.Random -> posts.randomOrNull()
} } ?: otherwise ?.select(repo, exclude)
} }
@Serializable(Prefer.Serializer::class) @Serializable(Prefer.Serializer::class)

View File

@ -16,6 +16,7 @@ dependencies {
api project(":plaguposter.ratings") api project(":plaguposter.ratings")
api project(":plaguposter.ratings.source") api project(":plaguposter.ratings.source")
api project(":plaguposter.ratings.selector") api project(":plaguposter.ratings.selector")
api project(":plaguposter.ratings.gc")
api libs.psql api libs.psql
} }

View File

@ -12,7 +12,8 @@
"dev.inmo.plaguposter.ratings.Plugin", "dev.inmo.plaguposter.ratings.Plugin",
"dev.inmo.plaguposter.ratings.source.Plugin", "dev.inmo.plaguposter.ratings.source.Plugin",
"dev.inmo.plaguposter.ratings.selector.Plugin", "dev.inmo.plaguposter.ratings.selector.Plugin",
"dev.inmo.plaguposter.triggers.selector_with_timer.Plugin" "dev.inmo.plaguposter.triggers.selector_with_timer.Plugin",
"dev.inmo.plaguposter.ratings.gc.Plugin"
], ],
"posts": { "posts": {
"targetChat": 12345678, "targetChat": 12345678,
@ -66,5 +67,12 @@
}, },
"timer_trigger": { "timer_trigger": {
"krontab": "0 30 2/4 * *" "krontab": "0 30 2/4 * *"
},
"gc": {
"autoclear": {
"rating": -2,
"autoClearKrontab": "0 0 0 * *",
"skipPostAge": 86400
}
} }
} }

View File

@ -7,6 +7,7 @@ String[] includes = [
":ratings", ":ratings",
":ratings:source", ":ratings:source",
":ratings:selector", ":ratings:selector",
":ratings:gc",
":triggers:command", ":triggers:command",
":triggers:selector_with_timer", ":triggers:selector_with_timer",
// ":settings", // ":settings",