From 1091f1141bab59c84dcb5890d5416b119d590125 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 12 Mar 2026 16:13:39 +0600 Subject: [PATCH 1/7] start 0.11.0 --- CHANGELOG.md | 2 ++ gradle.properties | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92ca351..d519a64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # PlaguPoster +## 0.11.0 + ## 0.10.1 * Dependencies update diff --git a/gradle.properties b/gradle.properties index 41c0213..ee83d75 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,4 +9,4 @@ android.enableJetifier=true # Project data group=dev.inmo -version=0.10.1 +version=0.11.0 From 18180e67f65c6eea5a28a4e12b070486c157c057 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 12 Mar 2026 16:12:52 +0600 Subject: [PATCH 2/7] made it buildable again --- build.gradle | 1 + changelog_parser.sh | 0 github_release.gradle | 12 +++++----- gradle/libs.versions.toml | 21 +++++++++------- inlines/src/jvmMain/kotlin/Plugin.kt | 1 - posts/panel/src/jvmMain/kotlin/Plugin.kt | 4 ---- .../src/jvmMain/kotlin/repos/PostsMessages.kt | 2 +- .../kotlin/exposed/ExposedContentInfoRepo.kt | 6 ++++- .../kotlin/exposed/ExposedPostsRepo.kt | 24 ++++++++++++------- ratings/gc/src/jvmMain/kotlin/Plugin.kt | 1 - ratings/source/src/jvmMain/kotlin/Plugin.kt | 1 - .../repos/ExposedPollsToMessagesInfoRepo.kt | 15 +++++++----- .../repos/ExposedPollsToPostsIdsRepo.kt | 11 +++++---- .../kotlin/exposed/ExposedRatingsRepo.kt | 18 ++++++++++---- triggers/command/src/jvmMain/kotlin/Plugin.kt | 1 - .../src/jvmMain/kotlin/Plugin.kt | 1 - .../jvmMain/kotlin/repo/ExposedTimersRepo.kt | 19 +++++++-------- 17 files changed, 78 insertions(+), 60 deletions(-) mode change 100644 => 100755 changelog_parser.sh diff --git a/build.gradle b/build.gradle index 323b197..a3d07be 100644 --- a/build.gradle +++ b/build.gradle @@ -10,6 +10,7 @@ buildscript { classpath libs.kotlin.gradle.plugin classpath libs.kotlin.serialization.plugin classpath libs.kotlin.dokka.plugin + classpath libs.github.release } } diff --git a/changelog_parser.sh b/changelog_parser.sh old mode 100644 new mode 100755 diff --git a/github_release.gradle b/github_release.gradle index 3e10ad6..716ec64 100644 --- a/github_release.gradle +++ b/github_release.gradle @@ -25,14 +25,14 @@ if (secretFile.exists() || project.hasProperty(githubTokenVariableName) || (gith githubRelease { token githubReleaseToken - owner "InsanusMokrassar" - repo "PlaguPoster" + owner = "InsanusMokrassar" + repo = "PlaguPoster" - tagName "v${project.version}" - releaseName "${project.version}" - targetCommitish "${project.version}" + tagName = "v${project.version}" + releaseName = "${project.version}" + targetCommitish = "${project.version}" - body getCurrentVersionChangelog() + body = getCurrentVersionChangelog() } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ac2302a..e64208a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,21 +1,23 @@ [versions] -kotlin = "2.2.0" -kotlin-serialization = "1.9.0" +kotlin = "2.3.10" +kotlin-serialization = "1.10.0" -plagubot = "10.7.0" -tgbotapi = "27.1.2" -microutils = "0.26.2" -kslog = "1.5.0" -krontab = "2.7.2" -plagubot-plugins = "0.24.5" +plagubot = "11.0.0" +tgbotapi = "32.0.0" +microutils = "0.29.1" +kslog = "1.6.0" +krontab = "2.8.0" +plagubot-plugins = "0.25.0" -nmcp="1.0.2" +nmcp = "1.4.4" dokka = "2.0.0" psql = "42.6.0" +github-release = "2.5.2" + [libraries] kotlin = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } @@ -44,6 +46,7 @@ psql = { module = "org.postgresql:postgresql", version.ref = "psql" } kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } kotlin-serialization-plugin = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlin" } kotlin-dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" } +github-release = { module = "com.github.breadmoirai:github-release", version.ref = "github-release" } [plugins] diff --git a/inlines/src/jvmMain/kotlin/Plugin.kt b/inlines/src/jvmMain/kotlin/Plugin.kt index a4a512e..ec09144 100644 --- a/inlines/src/jvmMain/kotlin/Plugin.kt +++ b/inlines/src/jvmMain/kotlin/Plugin.kt @@ -5,7 +5,6 @@ import dev.inmo.kslog.common.w import dev.inmo.plagubot.Plugin import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext import kotlinx.serialization.json.JsonObject -import org.jetbrains.exposed.sql.Database import org.koin.core.Koin import org.koin.core.module.Module diff --git a/posts/panel/src/jvmMain/kotlin/Plugin.kt b/posts/panel/src/jvmMain/kotlin/Plugin.kt index f8c6861..03d85b8 100644 --- a/posts/panel/src/jvmMain/kotlin/Plugin.kt +++ b/posts/panel/src/jvmMain/kotlin/Plugin.kt @@ -5,9 +5,6 @@ import dev.inmo.micro_utils.coroutines.runCatchingSafely import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.koin.getAllDistinct import dev.inmo.micro_utils.repos.* -import dev.inmo.micro_utils.repos.cache.cache.FullKVCache -import dev.inmo.micro_utils.repos.cache.cached -import dev.inmo.micro_utils.repos.cache.full.cached import dev.inmo.micro_utils.repos.cache.full.fullyCached import dev.inmo.plagubot.Plugin import dev.inmo.plagubot.registerConfig @@ -42,7 +39,6 @@ import dev.inmo.tgbotapi.utils.italic import kotlinx.coroutines.flow.first 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 diff --git a/posts/panel/src/jvmMain/kotlin/repos/PostsMessages.kt b/posts/panel/src/jvmMain/kotlin/repos/PostsMessages.kt index baa52b5..f40f7bf 100644 --- a/posts/panel/src/jvmMain/kotlin/repos/PostsMessages.kt +++ b/posts/panel/src/jvmMain/kotlin/repos/PostsMessages.kt @@ -8,7 +8,7 @@ import dev.inmo.tgbotapi.types.* import kotlinx.serialization.builtins.PairSerializer import kotlinx.serialization.builtins.serializer import kotlinx.serialization.json.Json -import org.jetbrains.exposed.sql.Database +import org.jetbrains.exposed.v1.jdbc.Database private val ChatIdToMessageSerializer = PairSerializer(FullChatIdentifierSerializer, MessageId.serializer()) diff --git a/posts/src/jvmMain/kotlin/exposed/ExposedContentInfoRepo.kt b/posts/src/jvmMain/kotlin/exposed/ExposedContentInfoRepo.kt index 9ac65d5..d749017 100644 --- a/posts/src/jvmMain/kotlin/exposed/ExposedContentInfoRepo.kt +++ b/posts/src/jvmMain/kotlin/exposed/ExposedContentInfoRepo.kt @@ -5,7 +5,11 @@ import dev.inmo.micro_utils.repos.KeyValuesRepo import dev.inmo.micro_utils.repos.exposed.* import dev.inmo.plaguposter.posts.models.* import dev.inmo.tgbotapi.types.* -import org.jetbrains.exposed.sql.* +import org.jetbrains.exposed.v1.core.Column +import org.jetbrains.exposed.v1.core.ReferenceOption +import org.jetbrains.exposed.v1.core.ResultRow +import org.jetbrains.exposed.v1.core.Table +import org.jetbrains.exposed.v1.jdbc.Database internal class ExposedContentInfoRepo( override val database: Database, diff --git a/posts/src/jvmMain/kotlin/exposed/ExposedPostsRepo.kt b/posts/src/jvmMain/kotlin/exposed/ExposedPostsRepo.kt index 3698799..01dfab5 100644 --- a/posts/src/jvmMain/kotlin/exposed/ExposedPostsRepo.kt +++ b/posts/src/jvmMain/kotlin/exposed/ExposedPostsRepo.kt @@ -13,11 +13,19 @@ import dev.inmo.tgbotapi.types.IdChatIdentifier import dev.inmo.tgbotapi.types.MessageId import kotlinx.coroutines.flow.* import kotlinx.serialization.json.Json -import org.jetbrains.exposed.sql.* -import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq -import org.jetbrains.exposed.sql.SqlExpressionBuilder.inList -import org.jetbrains.exposed.sql.statements.* -import org.jetbrains.exposed.sql.transactions.transaction +import org.jetbrains.exposed.v1.core.Op +import org.jetbrains.exposed.v1.core.ResultRow +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.core.inList +import org.jetbrains.exposed.v1.core.isNull +import org.jetbrains.exposed.v1.core.statements.InsertStatement +import org.jetbrains.exposed.v1.core.statements.UpdateBuilder +import org.jetbrains.exposed.v1.jdbc.Database +import org.jetbrains.exposed.v1.jdbc.deleteWhere +import org.jetbrains.exposed.v1.jdbc.insert +import org.jetbrains.exposed.v1.jdbc.selectAll +import org.jetbrains.exposed.v1.jdbc.transactions.transaction class ExposedPostsRepo( override val database: Database @@ -37,8 +45,8 @@ class ExposedPostsRepo( override val primaryKey: PrimaryKey = PrimaryKey(idColumn) - override val selectById: ISqlExpressionBuilder.(PostId) -> Op = { idColumn.eq(it.string) } - override val selectByIds: ISqlExpressionBuilder.(List) -> Op = { idColumn.inList(it.map { it.string }) } + override val selectById: (PostId) -> Op = { idColumn.eq(it.string) } + override val selectByIds: (List) -> Op = { idColumn.inList(it.map { it.string }) } override val ResultRow.asId: PostId get() = PostId(get(idColumn)) override val ResultRow.asObject: RegisteredPost @@ -133,7 +141,7 @@ class ExposedPostsRepo( val existsIds = posts.keys.toList() transaction(db = database) { val deleted = deleteWhere { - selectByIds(it, existsIds) + selectByIds(existsIds) } with(contentRepo) { deleteWhere { diff --git a/ratings/gc/src/jvmMain/kotlin/Plugin.kt b/ratings/gc/src/jvmMain/kotlin/Plugin.kt index fcacd9f..fe03a9e 100644 --- a/ratings/gc/src/jvmMain/kotlin/Plugin.kt +++ b/ratings/gc/src/jvmMain/kotlin/Plugin.kt @@ -25,7 +25,6 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onComman 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 diff --git a/ratings/source/src/jvmMain/kotlin/Plugin.kt b/ratings/source/src/jvmMain/kotlin/Plugin.kt index c226da5..e344899 100644 --- a/ratings/source/src/jvmMain/kotlin/Plugin.kt +++ b/ratings/source/src/jvmMain/kotlin/Plugin.kt @@ -54,7 +54,6 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.first 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 diff --git a/ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToMessagesInfoRepo.kt b/ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToMessagesInfoRepo.kt index d7d151a..f10e0f6 100644 --- a/ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToMessagesInfoRepo.kt +++ b/ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToMessagesInfoRepo.kt @@ -4,10 +4,13 @@ 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.* -import org.jetbrains.exposed.sql.* -import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq -import org.jetbrains.exposed.sql.SqlExpressionBuilder.isNull -import org.jetbrains.exposed.sql.statements.* +import org.jetbrains.exposed.v1.core.Op +import org.jetbrains.exposed.v1.core.ResultRow +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.core.isNull +import org.jetbrains.exposed.v1.core.statements.UpdateBuilder +import org.jetbrains.exposed.v1.jdbc.Database class ExposedPollsToMessagesInfoRepo( database: Database @@ -19,8 +22,8 @@ class ExposedPollsToMessagesInfoRepo( private val chatIdColumn = long("chat_id") private val threadIdColumn = long("thread_id").nullable().default(null) private val messageIdColumn = long("message_id") - override val selectById: ISqlExpressionBuilder.(PollId) -> Op = { keyColumn.eq(it.string) } - override val selectByValue: ISqlExpressionBuilder.(ShortMessageInfo) -> Op = { + override val selectById: (PollId) -> Op = { keyColumn.eq(it.string) } + override val selectByValue: (ShortMessageInfo) -> Op = { chatIdColumn.eq(it.chatId.chatId.long) .and(it.chatId.threadId?.let { threadIdColumn.eq(it.long) } ?: threadIdColumn.isNull()).and( messageIdColumn.eq(it.messageId.long) diff --git a/ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToPostsIdsRepo.kt b/ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToPostsIdsRepo.kt index 2804677..a7c161a 100644 --- a/ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToPostsIdsRepo.kt +++ b/ratings/source/src/jvmMain/kotlin/repos/ExposedPollsToPostsIdsRepo.kt @@ -4,16 +4,19 @@ 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.PollId -import org.jetbrains.exposed.sql.* -import org.jetbrains.exposed.sql.statements.* +import org.jetbrains.exposed.v1.core.Op +import org.jetbrains.exposed.v1.core.ResultRow +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.core.statements.UpdateBuilder +import org.jetbrains.exposed.v1.jdbc.Database class ExposedPollsToPostsIdsRepo( database: Database ) : PollsToPostsIdsRepo, AbstractExposedKeyValueRepo(database, "polls_to_posts") { override val keyColumn = text("poll_id") val postIdColumn = text("postId") - override val selectById: ISqlExpressionBuilder.(PollId) -> Op = { keyColumn.eq(it.string) } - override val selectByValue: ISqlExpressionBuilder.(PostId) -> Op = { postIdColumn.eq(it.string) } + override val selectById: (PollId) -> Op = { keyColumn.eq(it.string) } + override val selectByValue: (PostId) -> Op = { postIdColumn.eq(it.string) } override val ResultRow.asKey: PollId get() = PollId(get(keyColumn)) override val ResultRow.asObject: PostId diff --git a/ratings/src/jvmMain/kotlin/exposed/ExposedRatingsRepo.kt b/ratings/src/jvmMain/kotlin/exposed/ExposedRatingsRepo.kt index db39cae..13a4514 100644 --- a/ratings/src/jvmMain/kotlin/exposed/ExposedRatingsRepo.kt +++ b/ratings/src/jvmMain/kotlin/exposed/ExposedRatingsRepo.kt @@ -6,9 +6,17 @@ import dev.inmo.micro_utils.repos.exposed.keyvalue.AbstractExposedKeyValueRepo import dev.inmo.plaguposter.posts.models.PostId import dev.inmo.plaguposter.ratings.models.Rating import dev.inmo.plaguposter.ratings.repo.RatingsRepo -import org.jetbrains.exposed.sql.* -import org.jetbrains.exposed.sql.statements.* -import org.jetbrains.exposed.sql.transactions.transaction +import org.jetbrains.exposed.v1.core.Op +import org.jetbrains.exposed.v1.core.ResultRow +import org.jetbrains.exposed.v1.core.and +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.core.greaterEq +import org.jetbrains.exposed.v1.core.lessEq +import org.jetbrains.exposed.v1.core.notInList +import org.jetbrains.exposed.v1.core.statements.UpdateBuilder +import org.jetbrains.exposed.v1.jdbc.Database +import org.jetbrains.exposed.v1.jdbc.Query +import org.jetbrains.exposed.v1.jdbc.transactions.transaction class ExposedRatingsRepo ( database: Database @@ -18,8 +26,8 @@ class ExposedRatingsRepo ( ) { override val keyColumn = text("post_id") val ratingsColumn = double("rating") - override val selectById: ISqlExpressionBuilder.(PostId) -> Op = { keyColumn.eq(it.string) } - override val selectByValue: ISqlExpressionBuilder.(Rating) -> Op = { ratingsColumn.eq(it.double) } + override val selectById: (PostId) -> Op = { keyColumn.eq(it.string) } + override val selectByValue: (Rating) -> Op = { ratingsColumn.eq(it.double) } override val ResultRow.asKey: PostId get() = get(keyColumn).let(::PostId) override val ResultRow.asObject: Rating diff --git a/triggers/command/src/jvmMain/kotlin/Plugin.kt b/triggers/command/src/jvmMain/kotlin/Plugin.kt index 8f2e2b6..f0a8a3d 100644 --- a/triggers/command/src/jvmMain/kotlin/Plugin.kt +++ b/triggers/command/src/jvmMain/kotlin/Plugin.kt @@ -31,7 +31,6 @@ import dev.inmo.tgbotapi.types.message.textsources.regularTextSource import kotlinx.coroutines.flow.first 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 diff --git a/triggers/selector_with_timer/src/jvmMain/kotlin/Plugin.kt b/triggers/selector_with_timer/src/jvmMain/kotlin/Plugin.kt index f34da01..b0f30df 100644 --- a/triggers/selector_with_timer/src/jvmMain/kotlin/Plugin.kt +++ b/triggers/selector_with_timer/src/jvmMain/kotlin/Plugin.kt @@ -41,7 +41,6 @@ import kotlinx.coroutines.flow.collectIndexed import kotlinx.coroutines.flow.take import kotlinx.serialization.* import kotlinx.serialization.json.* -import org.jetbrains.exposed.sql.Database import org.koin.core.Koin import org.koin.core.module.Module diff --git a/triggers/timer/src/jvmMain/kotlin/repo/ExposedTimersRepo.kt b/triggers/timer/src/jvmMain/kotlin/repo/ExposedTimersRepo.kt index 9f63e1a..d6f8010 100644 --- a/triggers/timer/src/jvmMain/kotlin/repo/ExposedTimersRepo.kt +++ b/triggers/timer/src/jvmMain/kotlin/repo/ExposedTimersRepo.kt @@ -11,15 +11,12 @@ 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 +import org.jetbrains.exposed.v1.core.Op +import org.jetbrains.exposed.v1.core.ResultRow +import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.core.statements.UpdateBuilder +import org.jetbrains.exposed.v1.jdbc.Database +import org.jetbrains.exposed.v1.jdbc.transactions.transaction class ExposedTimersRepo( database: Database, @@ -31,8 +28,8 @@ class ExposedTimersRepo( ) { override val keyColumn = text("post_id") private val dateTimeColumn = long("date_time") - override val selectById: ISqlExpressionBuilder.(PostId) -> Op = { keyColumn.eq(it.string) } - override val selectByValue: ISqlExpressionBuilder.(DateTime) -> Op = { dateTimeColumn.eq(it.unixMillisLong) } + override val selectById: (PostId) -> Op = { keyColumn.eq(it.string) } + override val selectByValue: (DateTime) -> Op = { dateTimeColumn.eq(it.unixMillisLong) } override val ResultRow.asKey: PostId get() = PostId(get(keyColumn)) override val ResultRow.asObject: DateTime From 028f1f48e8b75d3e73f699ac2f91cdd4a3bd16d8 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 12 Mar 2026 16:31:29 +0600 Subject: [PATCH 3/7] add coloring of inline buttons --- posts/gc/src/jvmMain/kotlin/Plugin.kt | 3 ++- posts/panel/src/jvmMain/kotlin/Plugin.kt | 12 ++++++++---- posts_registrar/src/jvmMain/kotlin/Plugin.kt | 4 +++- ratings/source/src/jvmMain/kotlin/Plugin.kt | 15 ++++++++++++--- sample/config.json | 4 +++- triggers/command/src/jvmMain/kotlin/Plugin.kt | 2 +- .../src/commonMain/kotlin/TimerPanelButton.kt | 8 +++++++- 7 files changed, 36 insertions(+), 12 deletions(-) diff --git a/posts/gc/src/jvmMain/kotlin/Plugin.kt b/posts/gc/src/jvmMain/kotlin/Plugin.kt index b9c9fd2..2a5addf 100644 --- a/posts/gc/src/jvmMain/kotlin/Plugin.kt +++ b/posts/gc/src/jvmMain/kotlin/Plugin.kt @@ -33,6 +33,7 @@ import dev.inmo.tgbotapi.extensions.utils.extensions.sameMessage import dev.inmo.tgbotapi.extensions.utils.types.buttons.dataButton import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard import dev.inmo.tgbotapi.types.MilliSeconds +import dev.inmo.tgbotapi.types.buttons.KeyboardButtonStyle import dev.inmo.tgbotapi.utils.bold import kotlinx.coroutines.* import kotlinx.coroutines.flow.filter @@ -148,7 +149,7 @@ object Plugin : Plugin { message, text = "Are you sure want to trigger posts garbage collecting?", replyMarkup = flatInlineKeyboard { - dataButton("Sure", yesData) + dataButton("Sure", yesData, style = KeyboardButtonStyle.Primary) dataButton("No", noData) } ) diff --git a/posts/panel/src/jvmMain/kotlin/Plugin.kt b/posts/panel/src/jvmMain/kotlin/Plugin.kt index 03d85b8..3a5f0df 100644 --- a/posts/panel/src/jvmMain/kotlin/Plugin.kt +++ b/posts/panel/src/jvmMain/kotlin/Plugin.kt @@ -1,7 +1,9 @@ package dev.inmo.plaguposter.posts.panel import com.benasher44.uuid.uuid4 +import dev.inmo.micro_utils.coroutines.runCatchingLogging import dev.inmo.micro_utils.coroutines.runCatchingSafely +import dev.inmo.micro_utils.coroutines.subscribeLoggingDropExceptions import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.koin.getAllDistinct import dev.inmo.micro_utils.repos.* @@ -32,6 +34,7 @@ import dev.inmo.tgbotapi.types.MessageId import dev.inmo.tgbotapi.types.ReplyParameters import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup +import dev.inmo.tgbotapi.types.buttons.KeyboardButtonStyle import dev.inmo.tgbotapi.types.message.ParseMode import dev.inmo.tgbotapi.utils.bold import dev.inmo.tgbotapi.utils.buildEntities @@ -69,7 +72,8 @@ object Plugin : Plugin { PanelButtonBuilder { CallbackDataInlineKeyboardButton( text, - "refresh ${it.id.string}" + "refresh ${it.id.string}", + style = KeyboardButtonStyle.Primary ) } } @@ -97,7 +101,7 @@ object Plugin : Plugin { basePostsMessages } - postsRepo.newObjectsFlow.subscribeSafelyWithoutExceptions(this) { + postsRepo.newObjectsFlow.subscribeLoggingDropExceptions(this) { val firstContent = it.content.first() val buttons = api.buttonsBuilders.chunked(config.buttonsPerRow).mapNotNull { row -> row.mapNotNull { builder -> @@ -162,7 +166,7 @@ object Plugin : Plugin { edit( query.message, replyMarkup = flatInlineKeyboard { - dataButton("\uD83D\uDDD1", approveData) + dataButton("\uD83D\uDDD1", approveData, style = KeyboardButtonStyle.Danger) api.RootPanelButtonBuilder.buildButton(post) ?.let(::add) } ) @@ -184,7 +188,7 @@ object Plugin : Plugin { val postId = query.data.removePrefix("refresh ").let(::PostId) val (chatId, messageId) = postsMessages.get(postId) ?: return@onMessageDataCallbackQuery - runCatchingSafely { + runCatching { refreshPostMessage( postId, chatId, diff --git a/posts_registrar/src/jvmMain/kotlin/Plugin.kt b/posts_registrar/src/jvmMain/kotlin/Plugin.kt index 61a1365..b39c451 100644 --- a/posts_registrar/src/jvmMain/kotlin/Plugin.kt +++ b/posts_registrar/src/jvmMain/kotlin/Plugin.kt @@ -22,6 +22,7 @@ import dev.inmo.tgbotapi.extensions.utils.extensions.sameChat import dev.inmo.tgbotapi.extensions.utils.extensions.sameMessage import dev.inmo.tgbotapi.extensions.utils.textContentOrNull import dev.inmo.tgbotapi.extensions.utils.types.buttons.* +import dev.inmo.tgbotapi.types.buttons.KeyboardButtonStyle import dev.inmo.tgbotapi.utils.regular import kotlinx.coroutines.async import kotlinx.coroutines.flow.* @@ -56,7 +57,8 @@ object Plugin : Plugin { flatInlineKeyboard { dataButton( "Finish", - buttonUuid + buttonUuid, + style = KeyboardButtonStyle.Primary, ) } } else { diff --git a/ratings/source/src/jvmMain/kotlin/Plugin.kt b/ratings/source/src/jvmMain/kotlin/Plugin.kt index e344899..038e883 100644 --- a/ratings/source/src/jvmMain/kotlin/Plugin.kt +++ b/ratings/source/src/jvmMain/kotlin/Plugin.kt @@ -43,6 +43,7 @@ import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard import dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard import dev.inmo.tgbotapi.types.ReplyParameters import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton +import dev.inmo.tgbotapi.types.buttons.KeyboardButtonStyle import dev.inmo.tgbotapi.types.message.textsources.boldTextSource import dev.inmo.tgbotapi.types.message.textsources.regularTextSource import dev.inmo.tgbotapi.types.polls.InputPollOption @@ -67,7 +68,9 @@ object Plugin : Plugin { val variants: RatingsVariants, val autoAttach: Boolean, val ratingOfferText: String, - val panelButtonText: String = "Ratings" + val panelButtonText: String = "Ratings", + val ratingEnabledStyle: KeyboardButtonStyle? = null, + val ratingDisabledStyle: KeyboardButtonStyle? = null ) override fun Module.setupDI(params: JsonObject) { @@ -296,13 +299,19 @@ object Plugin : Plugin { panelApi ?.apply { add( PanelButtonBuilder { + val enabled = pollsToPostsIdsRepo.keys(it.id, firstPageWithOneElementPagination).results.any() CallbackDataInlineKeyboardButton( - config.panelButtonText + if (pollsToPostsIdsRepo.keys(it.id, firstPageWithOneElementPagination).results.any()) { + config.panelButtonText + if (enabled) { SuccessfulSymbol } else { UnsuccessfulSymbol }, - "toggle_ratings ${it.id.string}" + "toggle_ratings ${it.id.string}", + style = if (enabled) { + config.ratingEnabledStyle + } else { + config.ratingDisabledStyle + } ) } ) diff --git a/sample/config.json b/sample/config.json index 294fabc..74093e6 100644 --- a/sample/config.json +++ b/sample/config.json @@ -41,7 +41,9 @@ "Results": 0 }, "autoAttach": true, - "ratingOfferText": "What do you think about it?" + "ratingOfferText": "What do you think about it?", + "ratingEnabledStyle": "success", + "ratingDisabledStyle": "danger" }, "selector": { "items": [ diff --git a/triggers/command/src/jvmMain/kotlin/Plugin.kt b/triggers/command/src/jvmMain/kotlin/Plugin.kt index f0a8a3d..de6d330 100644 --- a/triggers/command/src/jvmMain/kotlin/Plugin.kt +++ b/triggers/command/src/jvmMain/kotlin/Plugin.kt @@ -113,7 +113,7 @@ object Plugin : Plugin { PanelButtonBuilder { CallbackDataInlineKeyboardButton( text, - "publish ${it.id.string}" + "publish ${it.id.string}", ) } ) diff --git a/triggers/timer/src/commonMain/kotlin/TimerPanelButton.kt b/triggers/timer/src/commonMain/kotlin/TimerPanelButton.kt index 729d3df..b3152f4 100644 --- a/triggers/timer/src/commonMain/kotlin/TimerPanelButton.kt +++ b/triggers/timer/src/commonMain/kotlin/TimerPanelButton.kt @@ -6,6 +6,7 @@ import dev.inmo.plaguposter.posts.models.RegisteredPost import dev.inmo.plaguposter.posts.panel.PanelButtonBuilder import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.InlineKeyboardButton +import dev.inmo.tgbotapi.types.buttons.KeyboardButtonStyle class TimerPanelButton( private val timersRepo: TimersRepo @@ -18,7 +19,12 @@ class TimerPanelButton( return CallbackDataInlineKeyboardButton( "⏰ ${ if (publishingTime == null) UnsuccessfulSymbol else SuccessfulSymbol }", - "$timerSetPrefix ${post.id}" + "$timerSetPrefix ${post.id}", + style = if (publishingTime == null) { + null + } else { + KeyboardButtonStyle.Success + } ) } From f06d91e38fe0b1727d8b739f6ba86f37e2de5003 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 12 Mar 2026 17:04:08 +0600 Subject: [PATCH 4/7] add templating of panelButtonText for ratings --- ratings/source/src/jvmMain/kotlin/Plugin.kt | 70 +++++++++++++++++---- sample/config.json | 4 +- 2 files changed, 62 insertions(+), 12 deletions(-) diff --git a/ratings/source/src/jvmMain/kotlin/Plugin.kt b/ratings/source/src/jvmMain/kotlin/Plugin.kt index 038e883..26f5ea5 100644 --- a/ratings/source/src/jvmMain/kotlin/Plugin.kt +++ b/ratings/source/src/jvmMain/kotlin/Plugin.kt @@ -3,6 +3,7 @@ package dev.inmo.plaguposter.ratings.source import com.benasher44.uuid.uuid4 import dev.inmo.kslog.common.e import dev.inmo.kslog.common.logger +import dev.inmo.micro_utils.common.fixed import dev.inmo.micro_utils.coroutines.runCatchingLogging import dev.inmo.micro_utils.coroutines.runCatchingSafely import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions @@ -44,6 +45,7 @@ import dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard import dev.inmo.tgbotapi.types.ReplyParameters import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton import dev.inmo.tgbotapi.types.buttons.KeyboardButtonStyle +import dev.inmo.tgbotapi.types.keyboardButtonRequestUserLimit import dev.inmo.tgbotapi.types.message.textsources.boldTextSource import dev.inmo.tgbotapi.types.message.textsources.regularTextSource import dev.inmo.tgbotapi.types.polls.InputPollOption @@ -58,9 +60,12 @@ import kotlinx.serialization.json.* import org.koin.core.Koin import org.koin.core.module.Module import org.koin.core.qualifier.named +import kotlin.math.roundToInt object Plugin : Plugin { private val ratingVariantsQualifier = named("ratingsVariants") + private const val attachedSymbolControlSymbol = "\${attached_symbol}" + private const val currentRatingControlSymbol = "\${rating}" @Serializable internal data class Config( @@ -68,9 +73,9 @@ object Plugin : Plugin { val variants: RatingsVariants, val autoAttach: Boolean, val ratingOfferText: String, - val panelButtonText: String = "Ratings", + val panelButtonText: String = "Ratings $attachedSymbolControlSymbol", val ratingEnabledStyle: KeyboardButtonStyle? = null, - val ratingDisabledStyle: KeyboardButtonStyle? = null + val ratingDisabledStyle: KeyboardButtonStyle? = null, ) override fun Module.setupDI(params: JsonObject) { @@ -299,18 +304,61 @@ object Plugin : Plugin { panelApi ?.apply { add( PanelButtonBuilder { - val enabled = pollsToPostsIdsRepo.keys(it.id, firstPageWithOneElementPagination).results.any() + suspend fun isEnabled() = pollsToPostsIdsRepo.keys(it.id, firstPageWithOneElementPagination).results.any() + val enabled = let { _ -> + var enabled: Boolean? = null + suspend { + enabled ?: (isEnabled().also { enabled = it }) + } + } + val rating = let { _ -> + var rating: Rating? = null + suspend { + if (isEnabled()) { + rating ?: ratingsRepo.get(it.id) ?.also { rating = it } + } else { + null + } + } + } + val resultText = config.panelButtonText + .let { + if (it.contains(attachedSymbolControlSymbol)) { + it.replace( + attachedSymbolControlSymbol, + if (enabled()) { + SuccessfulSymbol + } else { + UnsuccessfulSymbol + } + ) + } else { + it + } + } + .let { + val rating = rating() + if (rating != null) { + it.replace( + currentRatingControlSymbol, + rating.double.roundToInt().toString() + ) + } else { + it + } + } + .take(12) // maximal text appropriate for this button CallbackDataInlineKeyboardButton( - config.panelButtonText + if (enabled) { - SuccessfulSymbol - } else { - UnsuccessfulSymbol - }, + resultText, "toggle_ratings ${it.id.string}", - style = if (enabled) { - config.ratingEnabledStyle + style = if (config.ratingEnabledStyle != null || config.ratingDisabledStyle != null) { + if (enabled()) { + config.ratingEnabledStyle + } else { + config.ratingDisabledStyle + } } else { - config.ratingDisabledStyle + null } ) } diff --git a/sample/config.json b/sample/config.json index 74093e6..af6e77f 100644 --- a/sample/config.json +++ b/sample/config.json @@ -42,8 +42,10 @@ }, "autoAttach": true, "ratingOfferText": "What do you think about it?", + "panelButtonText": "Ratings ${attached_symbol}", "ratingEnabledStyle": "success", - "ratingDisabledStyle": "danger" + "ratingDisabledStyle": "danger", + "_note": "For panelButtonText you may use two control symbols: ${attached_symbol} to attach icon about enabled state and ${rating} to enable rating showing in button" }, "selector": { "items": [ From 815391d3f6046f9dae7ee1f4a94dd3889a2b481f Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 12 Mar 2026 17:24:48 +0600 Subject: [PATCH 5/7] add refreshing of panel after poll update --- ratings/source/src/jvmMain/kotlin/Plugin.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/ratings/source/src/jvmMain/kotlin/Plugin.kt b/ratings/source/src/jvmMain/kotlin/Plugin.kt index 26f5ea5..dfd4d00 100644 --- a/ratings/source/src/jvmMain/kotlin/Plugin.kt +++ b/ratings/source/src/jvmMain/kotlin/Plugin.kt @@ -128,6 +128,7 @@ object Plugin : Plugin { (variantsTransformer(it.textSources.makeSourceString()) ?.double ?.times(it.votes)) ?: 0.0 } ratingsRepo.set(postId, Rating(newRating)) + panelApi ?.forceRefresh(postId) } suspend fun attachPoll(postId: PostId): Boolean { From 53cc851944a4c624b1353c1543eb3dd7103a95f4 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 12 Mar 2026 17:39:47 +0600 Subject: [PATCH 6/7] small optimization of panelApi.forceRefresh in onPollUpdates --- ratings/source/src/jvmMain/kotlin/Plugin.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ratings/source/src/jvmMain/kotlin/Plugin.kt b/ratings/source/src/jvmMain/kotlin/Plugin.kt index dfd4d00..047892b 100644 --- a/ratings/source/src/jvmMain/kotlin/Plugin.kt +++ b/ratings/source/src/jvmMain/kotlin/Plugin.kt @@ -122,13 +122,22 @@ object Plugin : Plugin { val panelApi = koin.getOrNull() val chatConfig = koin.get() + val panelApiOnPollUpdatesUpdateTrigger: suspend (PostId) -> Unit = if (config.panelButtonText.contains(currentRatingControlSymbol)) { + { + panelApi ?.forceRefresh(it) + } + } else { + { + + } + } onPollUpdates (markerFactory = { it.id }) { poll -> val postId = pollsToPostsIdsRepo.get(poll.id) ?: return@onPollUpdates val newRating = poll.options.sumOf { (variantsTransformer(it.textSources.makeSourceString()) ?.double ?.times(it.votes)) ?: 0.0 } ratingsRepo.set(postId, Rating(newRating)) - panelApi ?.forceRefresh(postId) + panelApiOnPollUpdatesUpdateTrigger(postId) } suspend fun attachPoll(postId: PostId): Boolean { From a65e7598ba499a20df097e8c3df66093fb857a43 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 12 Mar 2026 17:56:05 +0600 Subject: [PATCH 7/7] small optimization of panel ratings button --- ratings/source/src/jvmMain/kotlin/Plugin.kt | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/ratings/source/src/jvmMain/kotlin/Plugin.kt b/ratings/source/src/jvmMain/kotlin/Plugin.kt index 047892b..e96959e 100644 --- a/ratings/source/src/jvmMain/kotlin/Plugin.kt +++ b/ratings/source/src/jvmMain/kotlin/Plugin.kt @@ -347,12 +347,19 @@ object Plugin : Plugin { } } .let { - val rating = rating() - if (rating != null) { - it.replace( - currentRatingControlSymbol, - rating.double.roundToInt().toString() - ) + if (it.contains(currentRatingControlSymbol)) { + val rating = rating() + if (rating != null) { + it.replace( + currentRatingControlSymbol, + rating.double.roundToInt().toString() + ) + } else { + it.replace( + currentRatingControlSymbol, + UnsuccessfulSymbol + ) + } } else { it }