From 1e393103c83a4d88d86bd1052011888c84063063 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sun, 4 Sep 2022 13:27:35 +0600 Subject: [PATCH] added ratings --- .../src/commonMain/kotlin/ShortMessageInfo.kt | 14 ++ common/src/commonMain/kotlin/Symbols.kt | 4 + gradle/libs.versions.toml | 4 + .../commonMain/kotlin/models/ChatConfig.kt | 4 + posts/src/jvmMain/kotlin/Plugin.kt | 9 +- posts_registrar/src/jvmMain/kotlin/Plugin.kt | 21 +- ratings/source/build.gradle | 22 ++ .../src/commonMain/kotlin/PackageInfo.kt | 1 + .../kotlin/models/RatingsVariants.kt | 35 ++++ .../kotlin/models/VariantTransformer.kt | 7 + .../kotlin/repos/PollsToMessagesInfoRepo.kt | 8 + .../kotlin/repos/PollsToPostsIdsRepo.kt | 7 + ratings/source/src/jvmMain/kotlin/Plugin.kt | 197 ++++++++++++++++++ .../repos/ExposedPollsToMessagesInfoRepo.kt | 49 +++++ .../repos/ExposedPollsToPostsIdsRepo.kt | 35 ++++ ratings/source/src/main/AndroidManifest.xml | 1 + ratings/src/jvmMain/kotlin/Plugin.kt | 8 +- runner/build.gradle | 3 + runner/config.json | 25 ++- runner/docker-compose.yml | 12 ++ settings.gradle | 3 +- 21 files changed, 437 insertions(+), 32 deletions(-) create mode 100644 common/src/commonMain/kotlin/ShortMessageInfo.kt create mode 100644 common/src/commonMain/kotlin/Symbols.kt create mode 100644 ratings/source/build.gradle create mode 100644 ratings/source/src/commonMain/kotlin/PackageInfo.kt create mode 100644 ratings/source/src/commonMain/kotlin/models/RatingsVariants.kt create mode 100644 ratings/source/src/commonMain/kotlin/models/VariantTransformer.kt create mode 100644 ratings/source/src/commonMain/kotlin/repos/PollsToMessagesInfoRepo.kt create mode 100644 ratings/source/src/commonMain/kotlin/repos/PollsToPostsIdsRepo.kt create mode 100644 ratings/source/src/jvmMain/kotlin/Plugin.kt create mode 100644 ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToMessagesInfoRepo.kt create mode 100644 ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToPostsIdsRepo.kt create mode 100644 ratings/source/src/main/AndroidManifest.xml create mode 100644 runner/docker-compose.yml diff --git a/common/src/commonMain/kotlin/ShortMessageInfo.kt b/common/src/commonMain/kotlin/ShortMessageInfo.kt new file mode 100644 index 0000000..2426f06 --- /dev/null +++ b/common/src/commonMain/kotlin/ShortMessageInfo.kt @@ -0,0 +1,14 @@ +package dev.inmo.plaguposter.common + +import dev.inmo.tgbotapi.types.ChatId +import dev.inmo.tgbotapi.types.MessageIdentifier +import dev.inmo.tgbotapi.types.message.abstracts.Message +import kotlinx.serialization.Serializable + +@Serializable +data class ShortMessageInfo( + val chatId: ChatId, + val messageId: MessageIdentifier +) + +fun Message.short() = ShortMessageInfo(chat.id, messageId) diff --git a/common/src/commonMain/kotlin/Symbols.kt b/common/src/commonMain/kotlin/Symbols.kt new file mode 100644 index 0000000..903505c --- /dev/null +++ b/common/src/commonMain/kotlin/Symbols.kt @@ -0,0 +1,4 @@ +package dev.inmo.plaguposter.common + +const val SuccessfulSymbol = "✓" +const val UnsuccessfulSymbol = "❌" diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 38ca6ed..af515ac 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,6 +8,8 @@ tgbotapi = "3.2.0" microutils = "0.12.6" kslog = "0.5.1" +psql = "42.3.6" + dexcount = "3.1.0" junit_version = "4.12" test_ext_junit_version = "1.1.3" @@ -37,6 +39,8 @@ microutils-repos-exposed = { module = "dev.inmo:micro_utils.repos.exposed", vers microutils-repos-cache = { module = "dev.inmo:micro_utils.repos.cache", version.ref = "microutils" } kslog = { module = "dev.inmo:kslog", version.ref = "kslog" } +psql = { module = "org.postgresql:postgresql", version.ref = "psql" } + # buildscript classpaths android-tools-build = { module = "com.android.tools.build:gradle", version.ref = "android-gradle-plugin" } diff --git a/posts/src/commonMain/kotlin/models/ChatConfig.kt b/posts/src/commonMain/kotlin/models/ChatConfig.kt index d67331a..5e4f5b1 100644 --- a/posts/src/commonMain/kotlin/models/ChatConfig.kt +++ b/posts/src/commonMain/kotlin/models/ChatConfig.kt @@ -1,11 +1,15 @@ package dev.inmo.plaguposter.posts.models import dev.inmo.tgbotapi.types.ChatId +import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable data class ChatConfig( + @SerialName("targetChat") val targetChatId: ChatId, + @SerialName("sourceChat") val sourceChatId: ChatId, + @SerialName("cacheChat") val cacheChatId: ChatId ) diff --git a/posts/src/jvmMain/kotlin/Plugin.kt b/posts/src/jvmMain/kotlin/Plugin.kt index 128fc64..3ef45b2 100644 --- a/posts/src/jvmMain/kotlin/Plugin.kt +++ b/posts/src/jvmMain/kotlin/Plugin.kt @@ -5,7 +5,7 @@ import dev.inmo.kslog.common.w import dev.inmo.plagubot.Plugin import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo import dev.inmo.plaguposter.posts.models.ChatConfig -import dev.inmo.plaguposter.posts.repo.PostsRepo +import dev.inmo.plaguposter.posts.repo.* import dev.inmo.plaguposter.posts.sending.PostPublisher import dev.inmo.tgbotapi.types.ChatId import kotlinx.serialization.SerialName @@ -13,6 +13,7 @@ import kotlinx.serialization.Serializable import kotlinx.serialization.json.* import org.jetbrains.exposed.sql.Database import org.koin.core.module.Module +import org.koin.dsl.binds object Plugin : Plugin { override fun Module.setupDI(database: Database, params: JsonObject) { @@ -23,7 +24,11 @@ object Plugin : Plugin { return } single { get().decodeFromJsonElement(ChatConfig.serializer(), configJson) } - single { ExposedPostsRepo(database) } + single { ExposedPostsRepo(database) } binds arrayOf( + PostsRepo::class, + ReadPostsRepo::class, + WritePostsRepo::class, + ) single { val config = get() PostPublisher(get(), get(), config.cacheChatId, config.targetChatId) diff --git a/posts_registrar/src/jvmMain/kotlin/Plugin.kt b/posts_registrar/src/jvmMain/kotlin/Plugin.kt index 0ca2ed6..0500fca 100644 --- a/posts_registrar/src/jvmMain/kotlin/Plugin.kt +++ b/posts_registrar/src/jvmMain/kotlin/Plugin.kt @@ -9,8 +9,7 @@ import dev.inmo.micro_utils.fsm.common.State import dev.inmo.micro_utils.repos.create import dev.inmo.plagubot.Plugin import dev.inmo.plaguposter.common.FirstSourceIsCommandsFilter -import dev.inmo.plaguposter.posts.models.NewPost -import dev.inmo.plaguposter.posts.models.PostContentInfo +import dev.inmo.plaguposter.posts.models.* import dev.inmo.plaguposter.posts.registrar.state.RegistrationState import dev.inmo.plaguposter.posts.repo.PostsRepo import dev.inmo.tgbotapi.extensions.api.delete @@ -41,24 +40,8 @@ import org.koin.core.module.Module @Serializable object Plugin : Plugin { - @Serializable - private data class Config( - @SerialName("sourceChat") - val sourceChatId: ChatId - ) - - override fun Module.setupDI(database: Database, params: JsonObject) { - val configJson = params["registrar"] ?: this@Plugin.let { - it.logger.w { - "Unable to load posts plugin due to absence of `registrar` key in config" - } - return - } - single { get().decodeFromJsonElement(Config.serializer(), configJson) } - } - override suspend fun BehaviourContextWithFSM.setupBotPlugin(koin: Koin) { - val config = koin.get() + val config = koin.get() val postsRepo = koin.get() strictlyOn {state: RegistrationState.InProcess -> diff --git a/ratings/source/build.gradle b/ratings/source/build.gradle new file mode 100644 index 0000000..ea7c956 --- /dev/null +++ b/ratings/source/build.gradle @@ -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.ratings") + } + } + jvmMain { + dependencies { + } + } + } +} diff --git a/ratings/source/src/commonMain/kotlin/PackageInfo.kt b/ratings/source/src/commonMain/kotlin/PackageInfo.kt new file mode 100644 index 0000000..5c7873a --- /dev/null +++ b/ratings/source/src/commonMain/kotlin/PackageInfo.kt @@ -0,0 +1 @@ +package dev.inmo.plaguposter.ratings.source diff --git a/ratings/source/src/commonMain/kotlin/models/RatingsVariants.kt b/ratings/source/src/commonMain/kotlin/models/RatingsVariants.kt new file mode 100644 index 0000000..2bce35a --- /dev/null +++ b/ratings/source/src/commonMain/kotlin/models/RatingsVariants.kt @@ -0,0 +1,35 @@ +package dev.inmo.plaguposter.ratings.source.models + +import dev.inmo.plaguposter.ratings.models.Rating +import kotlinx.serialization.KSerializer +import kotlinx.serialization.builtins.MapSerializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.json.* + +typealias RatingsVariants = Map +object RatingsVariantsSerializer : KSerializer { + val surrogate = JsonObject.serializer() + override val descriptor: SerialDescriptor = surrogate.descriptor + override fun deserialize(decoder: Decoder): RatingsVariants { + val o = surrogate.deserialize(decoder) + return o.entries.mapNotNull { (key, value) -> + val doubleValue = (value as? JsonPrimitive) ?.doubleOrNull ?: return@mapNotNull null + key to Rating(doubleValue) + }.toMap() + } + + override fun serialize(encoder: Encoder, value: RatingsVariants) { + surrogate.serialize( + encoder, + buildJsonObject { + value.forEach { (text, rating) -> + put(text, rating.double) + } + } + ) + } + +} diff --git a/ratings/source/src/commonMain/kotlin/models/VariantTransformer.kt b/ratings/source/src/commonMain/kotlin/models/VariantTransformer.kt new file mode 100644 index 0000000..558d89e --- /dev/null +++ b/ratings/source/src/commonMain/kotlin/models/VariantTransformer.kt @@ -0,0 +1,7 @@ +package dev.inmo.plaguposter.ratings.source.models + +import dev.inmo.plaguposter.ratings.models.Rating + +fun interface VariantTransformer { + operator fun invoke(from: String): Rating? +} diff --git a/ratings/source/src/commonMain/kotlin/repos/PollsToMessagesInfoRepo.kt b/ratings/source/src/commonMain/kotlin/repos/PollsToMessagesInfoRepo.kt new file mode 100644 index 0000000..6906d7f --- /dev/null +++ b/ratings/source/src/commonMain/kotlin/repos/PollsToMessagesInfoRepo.kt @@ -0,0 +1,8 @@ +package dev.inmo.plaguposter.ratings.source.repos + +import dev.inmo.micro_utils.repos.KeyValueRepo +import dev.inmo.plaguposter.common.ShortMessageInfo +import dev.inmo.plaguposter.posts.models.PostId +import dev.inmo.tgbotapi.types.PollIdentifier + +interface PollsToMessagesInfoRepo : KeyValueRepo diff --git a/ratings/source/src/commonMain/kotlin/repos/PollsToPostsIdsRepo.kt b/ratings/source/src/commonMain/kotlin/repos/PollsToPostsIdsRepo.kt new file mode 100644 index 0000000..90a673b --- /dev/null +++ b/ratings/source/src/commonMain/kotlin/repos/PollsToPostsIdsRepo.kt @@ -0,0 +1,7 @@ +package dev.inmo.plaguposter.ratings.source.repos + +import dev.inmo.micro_utils.repos.KeyValueRepo +import dev.inmo.plaguposter.posts.models.PostId +import dev.inmo.tgbotapi.types.PollIdentifier + +interface PollsToPostsIdsRepo : KeyValueRepo diff --git a/ratings/source/src/jvmMain/kotlin/Plugin.kt b/ratings/source/src/jvmMain/kotlin/Plugin.kt new file mode 100644 index 0000000..d20cf8e --- /dev/null +++ b/ratings/source/src/jvmMain/kotlin/Plugin.kt @@ -0,0 +1,197 @@ +package dev.inmo.plaguposter.ratings.source + +import dev.inmo.kslog.common.e +import dev.inmo.kslog.common.logger +import dev.inmo.micro_utils.coroutines.runCatchingSafely +import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions +import dev.inmo.micro_utils.pagination.firstPageWithOneElementPagination +import dev.inmo.micro_utils.repos.id +import dev.inmo.micro_utils.repos.pagination.getAll +import dev.inmo.micro_utils.repos.set +import dev.inmo.plagubot.Plugin +import dev.inmo.plaguposter.common.* +import dev.inmo.plaguposter.posts.models.ChatConfig +import dev.inmo.plaguposter.posts.models.PostId +import dev.inmo.plaguposter.posts.repo.PostsRepo +import dev.inmo.plaguposter.ratings.models.Rating +import dev.inmo.plaguposter.ratings.repo.RatingsRepo +import dev.inmo.plaguposter.ratings.source.models.* +import dev.inmo.plaguposter.ratings.source.repos.* +import dev.inmo.tgbotapi.extensions.api.delete +import dev.inmo.tgbotapi.extensions.api.edit.edit +import dev.inmo.tgbotapi.extensions.api.send.polls.sendRegularPoll +import dev.inmo.tgbotapi.extensions.api.send.reply +import dev.inmo.tgbotapi.extensions.api.send.send +import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext +import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.* +import dev.inmo.tgbotapi.extensions.utils.extensions.raw.poll +import dev.inmo.tgbotapi.extensions.utils.formatting.buildEntities +import dev.inmo.tgbotapi.types.message.textsources.regular +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 +import org.koin.core.qualifier.named + +object Plugin : Plugin { + private val ratingVariantsQualifier = named("ratingsVariants") + + @Serializable + internal data class Config( + @Serializable(RatingsVariantsSerializer::class) + val variants: RatingsVariants, + val autoAttach: Boolean, + val ratingOfferText: String + ) + + override fun Module.setupDI(database: Database, params: JsonObject) { + single { + get().decodeFromJsonElement(Config.serializer(), params["ratingsPolls"] ?: error("Unable to load config for rating polls in $params")) + } + single(ratingVariantsQualifier) { get().variants } + single { ExposedPollsToPostsIdsRepo(database) } + single { ExposedPollsToMessagesInfoRepo(database) } + single { + val ratingsSettings = get(ratingVariantsQualifier) + VariantTransformer { + ratingsSettings[it] + } + } + } + + override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) { + val pollsToPostsIdsRepo = koin.get() + val pollsToMessageInfoRepo = koin.get() + val variantsTransformer = koin.get() + val ratingsRepo = koin.get() + val postsRepo = koin.get() + val config = koin.get() + + onPollUpdates (markerFactory = { it.id }) { poll -> + val postId = pollsToPostsIdsRepo.get(poll.id) ?: return@onPollUpdates + val newRating = poll.options.sumOf { + (variantsTransformer(it.text) ?.double ?.times(it.votes)) ?: 0.0 + } + ratingsRepo.set(postId, Rating(newRating)) + } + + suspend fun attachPoll(postId: PostId): Boolean { + if (pollsToPostsIdsRepo.keys(postId, firstPageWithOneElementPagination).results.isNotEmpty()) { + return false + } + + val post = postsRepo.getById(postId) ?: return false + for (content in post.content) { + runCatchingSafely { + val sent = send( + content.chatId, + config.ratingOfferText, + config.variants.keys.toList(), + replyToMessageId = content.messageId + ) + pollsToPostsIdsRepo.set(sent.content.poll.id, postId) + pollsToMessageInfoRepo.set(sent.content.poll.id, sent.short()) + }.getOrNull() ?: continue + return true + } + return false + } + + suspend fun detachPoll(postId: PostId): Boolean { + val postIds = pollsToPostsIdsRepo.getAll { keys(postId, it) }.takeIf { it.isNotEmpty() } ?: return false + return postIds.map { (pollId) -> + val messageInfo = pollsToMessageInfoRepo.get(pollId) ?: return@map false + runCatchingSafely { + delete(messageInfo.chatId, messageInfo.messageId) + }.onFailure { + this@Plugin.logger.e(it) { "Something went wrong when trying to remove ratings message ($messageInfo) for post $postId" } + }.isSuccess + }.any().also { + if (it) { + pollsToPostsIdsRepo.unset(postIds.map { it.id }) + pollsToMessageInfoRepo.unset(postIds.map { it.id }) + } + } + } + + postsRepo.deletedObjectsIdsFlow.subscribeSafelyWithoutExceptions(this) { postId -> + detachPoll(postId) + } + + if (config.autoAttach) { + postsRepo.newObjectsFlow.subscribeSafelyWithoutExceptions(this) { + attachPoll(it.id) + } + } + + onCommand("attach_ratings", requireOnlyCommandInMessage = true) { + val replyTo = it.replyTo ?: run { + reply( + it, + "You should reply to post message to attach ratings" + ) + return@onCommand + } + + val postId = postsRepo.getIdByChatAndMessage(replyTo.chat.id, replyTo.messageId) ?: run { + reply( + it, + "Unable to find post where the message in reply is presented" + ) + return@onCommand + } + + if (attachPoll(postId)) { + runCatchingSafely { + edit( + it, + it.content.textSources + regular(" $SuccessfulSymbol") + ) + } + } else { + runCatchingSafely { + edit( + it, + it.content.textSources + regular(" $UnsuccessfulSymbol") + ) + } + } + } + + onCommand("detach_ratings", requireOnlyCommandInMessage = true) { + val replyTo = it.replyTo ?: run { + reply( + it, + "You should reply to post message to detach ratings" + ) + return@onCommand + } + + val postId = postsRepo.getIdByChatAndMessage(replyTo.chat.id, replyTo.messageId) ?: run { + reply( + it, + "Unable to find post where the message in reply is presented" + ) + return@onCommand + } + + + if (detachPoll(postId)) { + runCatchingSafely { + edit( + it, + it.content.textSources + regular(" $SuccessfulSymbol") + ) + } + } else { + runCatchingSafely { + edit( + it, + it.content.textSources + regular(" $UnsuccessfulSymbol") + ) + } + } + } + } +} diff --git a/ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToMessagesInfoRepo.kt b/ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToMessagesInfoRepo.kt new file mode 100644 index 0000000..bd0f9d3 --- /dev/null +++ b/ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToMessagesInfoRepo.kt @@ -0,0 +1,49 @@ +package dev.inmo.plaguposter.ratings.source.repos + +import dev.inmo.micro_utils.repos.exposed.initTable +import dev.inmo.micro_utils.repos.exposed.keyvalue.AbstractExposedKeyValueRepo +import dev.inmo.plaguposter.common.ShortMessageInfo +import dev.inmo.tgbotapi.types.ChatId +import dev.inmo.tgbotapi.types.PollIdentifier +import org.jetbrains.exposed.sql.* +import org.jetbrains.exposed.sql.statements.InsertStatement +import org.jetbrains.exposed.sql.statements.UpdateStatement + +class ExposedPollsToMessagesInfoRepo( + database: Database +) : PollsToMessagesInfoRepo, AbstractExposedKeyValueRepo( + database, + "polls_to_their_messages_info" +) { + override val keyColumn = text("poll_id") + private val chatIdColumn = long("chat_id") + private val messageIdColumn = long("message_id") + override val selectById: SqlExpressionBuilder.(PollIdentifier) -> Op = { keyColumn.eq(it) } + override val selectByValue: SqlExpressionBuilder.(ShortMessageInfo) -> Op = { + chatIdColumn.eq(it.chatId.chatId).and( + messageIdColumn.eq(it.messageId) + ) + } + override val ResultRow.asKey: PollIdentifier + get() = get(keyColumn) + override val ResultRow.asObject: ShortMessageInfo + get() = ShortMessageInfo( + get(chatIdColumn).let(::ChatId), + get(messageIdColumn) + ) + + init { + initTable() + } + + override fun update(k: PollIdentifier, v: ShortMessageInfo, it: UpdateStatement) { + it[chatIdColumn] = v.chatId.chatId + it[messageIdColumn] = v.messageId + } + + override fun insert(k: PollIdentifier, v: ShortMessageInfo, it: InsertStatement) { + it[keyColumn] = k + it[chatIdColumn] = v.chatId.chatId + it[messageIdColumn] = v.messageId + } +} diff --git a/ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToPostsIdsRepo.kt b/ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToPostsIdsRepo.kt new file mode 100644 index 0000000..66a7ba4 --- /dev/null +++ b/ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToPostsIdsRepo.kt @@ -0,0 +1,35 @@ +package dev.inmo.plaguposter.ratings.source.repos + +import dev.inmo.micro_utils.repos.exposed.initTable +import dev.inmo.micro_utils.repos.exposed.keyvalue.AbstractExposedKeyValueRepo +import dev.inmo.plaguposter.posts.models.PostId +import dev.inmo.tgbotapi.types.PollIdentifier +import org.jetbrains.exposed.sql.* +import org.jetbrains.exposed.sql.statements.InsertStatement +import org.jetbrains.exposed.sql.statements.UpdateStatement + +class ExposedPollsToPostsIdsRepo( + database: Database +) : PollsToPostsIdsRepo, AbstractExposedKeyValueRepo(database, "polls_to_posts") { + override val keyColumn = text("poll_id") + val postIdColumn = text("postId") + override val selectById: SqlExpressionBuilder.(PollIdentifier) -> Op = { keyColumn.eq(it) } + override val selectByValue: SqlExpressionBuilder.(PostId) -> Op = { postIdColumn.eq(it.string) } + override val ResultRow.asKey: PollIdentifier + get() = get(keyColumn) + override val ResultRow.asObject: PostId + get() = get(postIdColumn).let(::PostId) + + init { + initTable() + } + + override fun update(k: PollIdentifier, v: PostId, it: UpdateStatement) { + it[postIdColumn] = v.string + } + + override fun insert(k: PollIdentifier, v: PostId, it: InsertStatement) { + it[keyColumn] = k + it[postIdColumn] = v.string + } +} diff --git a/ratings/source/src/main/AndroidManifest.xml b/ratings/source/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f19f4fb --- /dev/null +++ b/ratings/source/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/ratings/src/jvmMain/kotlin/Plugin.kt b/ratings/src/jvmMain/kotlin/Plugin.kt index f602f06..9955074 100644 --- a/ratings/src/jvmMain/kotlin/Plugin.kt +++ b/ratings/src/jvmMain/kotlin/Plugin.kt @@ -3,12 +3,18 @@ package dev.inmo.plaguposter.ratings import dev.inmo.plagubot.Plugin import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo import dev.inmo.plaguposter.ratings.exposed.ExposedRatingsRepo +import dev.inmo.plaguposter.ratings.repo.* import kotlinx.serialization.json.* import org.jetbrains.exposed.sql.Database import org.koin.core.module.Module +import org.koin.dsl.binds object Plugin : Plugin { override fun Module.setupDI(database: Database, params: JsonObject) { - single { ExposedRatingsRepo(database, get().idColumn) } + single { ExposedRatingsRepo(database, get().idColumn) } binds arrayOf( + RatingsRepo::class, + ReadRatingsRepo::class, + WriteRatingsRepo::class, + ) } } diff --git a/runner/build.gradle b/runner/build.gradle index 7548453..550251b 100644 --- a/runner/build.gradle +++ b/runner/build.gradle @@ -12,6 +12,9 @@ dependencies { api project(":plaguposter.posts_registrar") api project(":plaguposter.triggers.command") api project(":plaguposter.ratings") + api project(":plaguposter.ratings.source") + + api libs.psql } application { diff --git a/runner/config.json b/runner/config.json index b140d31..3d2b0d3 100644 --- a/runner/config.json +++ b/runner/config.json @@ -1,21 +1,28 @@ { "database": { - "url": "jdbc:sqlite:file:test?mode=memory&cache=shared IT IS JUST EXAMPLE", - "driver": "org.sqlite.JDBC", - "username": "OPTIONAL username", - "password": "OPTIONAL password", - "initAutomatically": false + "url": "jdbc:postgresql://127.0.0.1:8091/test", + "username": "test", + "password": "test", + "driver": "org.postgresql.Driver" }, "botToken": "1234567890:ABCDEFGHIJKLMNOP_qrstuvwxyz12345678", "plugins": [ "dev.inmo.plaguposter.posts.Plugin", - "dev.inmo.plaguposter.posts.registrar.Plugin" + "dev.inmo.plaguposter.posts.registrar.Plugin", + "dev.inmo.plaguposter.ratings.Plugin", + "dev.inmo.plaguposter.ratings.source.Plugin" ], "posts": { "targetChat": 12345678, - "cacheChat": 12345678 - }, - "registrar": { + "cacheChat": 12345678, "sourceChat": 12345678 + }, + "ratingsPolls": { + "variants": { + "Ok": 1, + "Not ok": -1 + }, + "autoAttach": true, + "ratingOfferText": "What do you think about it?" } } diff --git a/runner/docker-compose.yml b/runner/docker-compose.yml new file mode 100644 index 0000000..8129b38 --- /dev/null +++ b/runner/docker-compose.yml @@ -0,0 +1,12 @@ +version: "3.4" + +services: + plaguposter_postgres: + image: postgres + container_name: "plaguposter_postgres" + environment: + POSTGRES_USER: "test" + POSTGRES_PASSWORD: "test" + POSTGRES_DB: "test" + ports: + - "8091:5432" diff --git a/settings.gradle b/settings.gradle index 026d646..ffb1846 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,8 +5,9 @@ String[] includes = [ ":posts", ":posts_registrar", ":ratings", + ":ratings:source", ":triggers:command", - ":settings", +// ":settings", ":runner" ]