mirror of
https://github.com/InsanusMokrassar/PlaguPoster.git
synced 2024-11-25 08:58:45 +00:00
added ratings
This commit is contained in:
parent
18b2e7b3c4
commit
1e393103c8
14
common/src/commonMain/kotlin/ShortMessageInfo.kt
Normal file
14
common/src/commonMain/kotlin/ShortMessageInfo.kt
Normal file
@ -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)
|
4
common/src/commonMain/kotlin/Symbols.kt
Normal file
4
common/src/commonMain/kotlin/Symbols.kt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
package dev.inmo.plaguposter.common
|
||||||
|
|
||||||
|
const val SuccessfulSymbol = "✓"
|
||||||
|
const val UnsuccessfulSymbol = "❌"
|
@ -8,6 +8,8 @@ tgbotapi = "3.2.0"
|
|||||||
microutils = "0.12.6"
|
microutils = "0.12.6"
|
||||||
kslog = "0.5.1"
|
kslog = "0.5.1"
|
||||||
|
|
||||||
|
psql = "42.3.6"
|
||||||
|
|
||||||
dexcount = "3.1.0"
|
dexcount = "3.1.0"
|
||||||
junit_version = "4.12"
|
junit_version = "4.12"
|
||||||
test_ext_junit_version = "1.1.3"
|
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" }
|
microutils-repos-cache = { module = "dev.inmo:micro_utils.repos.cache", version.ref = "microutils" }
|
||||||
kslog = { module = "dev.inmo:kslog", version.ref = "kslog" }
|
kslog = { module = "dev.inmo:kslog", version.ref = "kslog" }
|
||||||
|
|
||||||
|
psql = { module = "org.postgresql:postgresql", version.ref = "psql" }
|
||||||
|
|
||||||
# buildscript classpaths
|
# buildscript classpaths
|
||||||
|
|
||||||
android-tools-build = { module = "com.android.tools.build:gradle", version.ref = "android-gradle-plugin" }
|
android-tools-build = { module = "com.android.tools.build:gradle", version.ref = "android-gradle-plugin" }
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
package dev.inmo.plaguposter.posts.models
|
package dev.inmo.plaguposter.posts.models
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.types.ChatId
|
import dev.inmo.tgbotapi.types.ChatId
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class ChatConfig(
|
data class ChatConfig(
|
||||||
|
@SerialName("targetChat")
|
||||||
val targetChatId: ChatId,
|
val targetChatId: ChatId,
|
||||||
|
@SerialName("sourceChat")
|
||||||
val sourceChatId: ChatId,
|
val sourceChatId: ChatId,
|
||||||
|
@SerialName("cacheChat")
|
||||||
val cacheChatId: ChatId
|
val cacheChatId: ChatId
|
||||||
)
|
)
|
||||||
|
@ -5,7 +5,7 @@ import dev.inmo.kslog.common.w
|
|||||||
import dev.inmo.plagubot.Plugin
|
import dev.inmo.plagubot.Plugin
|
||||||
import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo
|
import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo
|
||||||
import dev.inmo.plaguposter.posts.models.ChatConfig
|
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.plaguposter.posts.sending.PostPublisher
|
||||||
import dev.inmo.tgbotapi.types.ChatId
|
import dev.inmo.tgbotapi.types.ChatId
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
@ -13,6 +13,7 @@ import kotlinx.serialization.Serializable
|
|||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import org.jetbrains.exposed.sql.Database
|
import org.jetbrains.exposed.sql.Database
|
||||||
import org.koin.core.module.Module
|
import org.koin.core.module.Module
|
||||||
|
import org.koin.dsl.binds
|
||||||
|
|
||||||
object Plugin : Plugin {
|
object Plugin : Plugin {
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(database: Database, params: JsonObject) {
|
||||||
@ -23,7 +24,11 @@ object Plugin : Plugin {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
single { get<Json>().decodeFromJsonElement(ChatConfig.serializer(), configJson) }
|
single { get<Json>().decodeFromJsonElement(ChatConfig.serializer(), configJson) }
|
||||||
single<PostsRepo> { ExposedPostsRepo(database) }
|
single { ExposedPostsRepo(database) } binds arrayOf(
|
||||||
|
PostsRepo::class,
|
||||||
|
ReadPostsRepo::class,
|
||||||
|
WritePostsRepo::class,
|
||||||
|
)
|
||||||
single {
|
single {
|
||||||
val config = get<ChatConfig>()
|
val config = get<ChatConfig>()
|
||||||
PostPublisher(get(), get(), config.cacheChatId, config.targetChatId)
|
PostPublisher(get(), get(), config.cacheChatId, config.targetChatId)
|
||||||
|
@ -9,8 +9,7 @@ import dev.inmo.micro_utils.fsm.common.State
|
|||||||
import dev.inmo.micro_utils.repos.create
|
import dev.inmo.micro_utils.repos.create
|
||||||
import dev.inmo.plagubot.Plugin
|
import dev.inmo.plagubot.Plugin
|
||||||
import dev.inmo.plaguposter.common.FirstSourceIsCommandsFilter
|
import dev.inmo.plaguposter.common.FirstSourceIsCommandsFilter
|
||||||
import dev.inmo.plaguposter.posts.models.NewPost
|
import dev.inmo.plaguposter.posts.models.*
|
||||||
import dev.inmo.plaguposter.posts.models.PostContentInfo
|
|
||||||
import dev.inmo.plaguposter.posts.registrar.state.RegistrationState
|
import dev.inmo.plaguposter.posts.registrar.state.RegistrationState
|
||||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||||
import dev.inmo.tgbotapi.extensions.api.delete
|
import dev.inmo.tgbotapi.extensions.api.delete
|
||||||
@ -41,24 +40,8 @@ import org.koin.core.module.Module
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
object Plugin : Plugin {
|
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<Json>().decodeFromJsonElement(Config.serializer(), configJson) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun BehaviourContextWithFSM<State>.setupBotPlugin(koin: Koin) {
|
override suspend fun BehaviourContextWithFSM<State>.setupBotPlugin(koin: Koin) {
|
||||||
val config = koin.get<Config>()
|
val config = koin.get<ChatConfig>()
|
||||||
val postsRepo = koin.get<PostsRepo>()
|
val postsRepo = koin.get<PostsRepo>()
|
||||||
|
|
||||||
strictlyOn {state: RegistrationState.InProcess ->
|
strictlyOn {state: RegistrationState.InProcess ->
|
||||||
|
22
ratings/source/build.gradle
Normal file
22
ratings/source/build.gradle
Normal 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.ratings")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jvmMain {
|
||||||
|
dependencies {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
ratings/source/src/commonMain/kotlin/PackageInfo.kt
Normal file
1
ratings/source/src/commonMain/kotlin/PackageInfo.kt
Normal file
@ -0,0 +1 @@
|
|||||||
|
package dev.inmo.plaguposter.ratings.source
|
@ -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<String, Rating>
|
||||||
|
object RatingsVariantsSerializer : KSerializer<RatingsVariants> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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?
|
||||||
|
}
|
@ -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<PollIdentifier, ShortMessageInfo>
|
@ -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<PollIdentifier, PostId>
|
197
ratings/source/src/jvmMain/kotlin/Plugin.kt
Normal file
197
ratings/source/src/jvmMain/kotlin/Plugin.kt
Normal file
@ -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<Json>().decodeFromJsonElement(Config.serializer(), params["ratingsPolls"] ?: error("Unable to load config for rating polls in $params"))
|
||||||
|
}
|
||||||
|
single<RatingsVariants>(ratingVariantsQualifier) { get<Config>().variants }
|
||||||
|
single<PollsToPostsIdsRepo> { ExposedPollsToPostsIdsRepo(database) }
|
||||||
|
single<PollsToMessagesInfoRepo> { ExposedPollsToMessagesInfoRepo(database) }
|
||||||
|
single<VariantTransformer> {
|
||||||
|
val ratingsSettings = get<RatingsVariants>(ratingVariantsQualifier)
|
||||||
|
VariantTransformer {
|
||||||
|
ratingsSettings[it]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) {
|
||||||
|
val pollsToPostsIdsRepo = koin.get<PollsToPostsIdsRepo>()
|
||||||
|
val pollsToMessageInfoRepo = koin.get<PollsToMessagesInfoRepo>()
|
||||||
|
val variantsTransformer = koin.get<VariantTransformer>()
|
||||||
|
val ratingsRepo = koin.get<RatingsRepo>()
|
||||||
|
val postsRepo = koin.get<PostsRepo>()
|
||||||
|
val config = koin.get<Config>()
|
||||||
|
|
||||||
|
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")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<PollIdentifier, ShortMessageInfo>(
|
||||||
|
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<Boolean> = { keyColumn.eq(it) }
|
||||||
|
override val selectByValue: SqlExpressionBuilder.(ShortMessageInfo) -> Op<Boolean> = {
|
||||||
|
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<Number>) {
|
||||||
|
it[keyColumn] = k
|
||||||
|
it[chatIdColumn] = v.chatId.chatId
|
||||||
|
it[messageIdColumn] = v.messageId
|
||||||
|
}
|
||||||
|
}
|
@ -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<PollIdentifier, PostId>(database, "polls_to_posts") {
|
||||||
|
override val keyColumn = text("poll_id")
|
||||||
|
val postIdColumn = text("postId")
|
||||||
|
override val selectById: SqlExpressionBuilder.(PollIdentifier) -> Op<Boolean> = { keyColumn.eq(it) }
|
||||||
|
override val selectByValue: SqlExpressionBuilder.(PostId) -> Op<Boolean> = { 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<Number>) {
|
||||||
|
it[keyColumn] = k
|
||||||
|
it[postIdColumn] = v.string
|
||||||
|
}
|
||||||
|
}
|
1
ratings/source/src/main/AndroidManifest.xml
Normal file
1
ratings/source/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1 @@
|
|||||||
|
<manifest package="dev.inmo.plaguposter.ratings.source"/>
|
@ -3,12 +3,18 @@ package dev.inmo.plaguposter.ratings
|
|||||||
import dev.inmo.plagubot.Plugin
|
import dev.inmo.plagubot.Plugin
|
||||||
import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo
|
import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo
|
||||||
import dev.inmo.plaguposter.ratings.exposed.ExposedRatingsRepo
|
import dev.inmo.plaguposter.ratings.exposed.ExposedRatingsRepo
|
||||||
|
import dev.inmo.plaguposter.ratings.repo.*
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import org.jetbrains.exposed.sql.Database
|
import org.jetbrains.exposed.sql.Database
|
||||||
import org.koin.core.module.Module
|
import org.koin.core.module.Module
|
||||||
|
import org.koin.dsl.binds
|
||||||
|
|
||||||
object Plugin : Plugin {
|
object Plugin : Plugin {
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(database: Database, params: JsonObject) {
|
||||||
single { ExposedRatingsRepo(database, get<ExposedPostsRepo>().idColumn) }
|
single { ExposedRatingsRepo(database, get<ExposedPostsRepo>().idColumn) } binds arrayOf(
|
||||||
|
RatingsRepo::class,
|
||||||
|
ReadRatingsRepo::class,
|
||||||
|
WriteRatingsRepo::class,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,9 @@ dependencies {
|
|||||||
api project(":plaguposter.posts_registrar")
|
api project(":plaguposter.posts_registrar")
|
||||||
api project(":plaguposter.triggers.command")
|
api project(":plaguposter.triggers.command")
|
||||||
api project(":plaguposter.ratings")
|
api project(":plaguposter.ratings")
|
||||||
|
api project(":plaguposter.ratings.source")
|
||||||
|
|
||||||
|
api libs.psql
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
|
@ -1,21 +1,28 @@
|
|||||||
{
|
{
|
||||||
"database": {
|
"database": {
|
||||||
"url": "jdbc:sqlite:file:test?mode=memory&cache=shared IT IS JUST EXAMPLE",
|
"url": "jdbc:postgresql://127.0.0.1:8091/test",
|
||||||
"driver": "org.sqlite.JDBC",
|
"username": "test",
|
||||||
"username": "OPTIONAL username",
|
"password": "test",
|
||||||
"password": "OPTIONAL password",
|
"driver": "org.postgresql.Driver"
|
||||||
"initAutomatically": false
|
|
||||||
},
|
},
|
||||||
"botToken": "1234567890:ABCDEFGHIJKLMNOP_qrstuvwxyz12345678",
|
"botToken": "1234567890:ABCDEFGHIJKLMNOP_qrstuvwxyz12345678",
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"dev.inmo.plaguposter.posts.Plugin",
|
"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": {
|
"posts": {
|
||||||
"targetChat": 12345678,
|
"targetChat": 12345678,
|
||||||
"cacheChat": 12345678
|
"cacheChat": 12345678,
|
||||||
},
|
|
||||||
"registrar": {
|
|
||||||
"sourceChat": 12345678
|
"sourceChat": 12345678
|
||||||
|
},
|
||||||
|
"ratingsPolls": {
|
||||||
|
"variants": {
|
||||||
|
"Ok": 1,
|
||||||
|
"Not ok": -1
|
||||||
|
},
|
||||||
|
"autoAttach": true,
|
||||||
|
"ratingOfferText": "What do you think about it?"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
runner/docker-compose.yml
Normal file
12
runner/docker-compose.yml
Normal file
@ -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"
|
@ -5,8 +5,9 @@ String[] includes = [
|
|||||||
":posts",
|
":posts",
|
||||||
":posts_registrar",
|
":posts_registrar",
|
||||||
":ratings",
|
":ratings",
|
||||||
|
":ratings:source",
|
||||||
":triggers:command",
|
":triggers:command",
|
||||||
":settings",
|
// ":settings",
|
||||||
":runner"
|
":runner"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user