diff --git a/posts/src/commonMain/kotlin/models/ChatConfig.kt b/common/src/commonMain/kotlin/ChatConfig.kt similarity index 88% rename from posts/src/commonMain/kotlin/models/ChatConfig.kt rename to common/src/commonMain/kotlin/ChatConfig.kt index 5e4f5b1..96f1442 100644 --- a/posts/src/commonMain/kotlin/models/ChatConfig.kt +++ b/common/src/commonMain/kotlin/ChatConfig.kt @@ -1,4 +1,4 @@ -package dev.inmo.plaguposter.posts.models +package dev.inmo.plaguposter.common import dev.inmo.tgbotapi.types.ChatId import kotlinx.serialization.SerialName diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 718a53c..c1e40fb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,11 +3,12 @@ kotlin = "1.7.10" kotlin-serialization = "1.4.0" -plagubot = "2.3.0" +plagubot = "2.3.1" tgbotapi = "3.2.1" microutils = "0.12.11" kslog = "0.5.1" krontab = "0.8.0" +tgbotapi-libraries = "0.5.3" psql = "42.3.6" @@ -33,6 +34,7 @@ android-test-junit = { module = "androidx.test.ext:junit", version.ref = "test_e android-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso_core" } tgbotapi = { module = "dev.inmo:tgbotapi", version.ref = "tgbotapi" } +tgbotapi-admins = { module = "dev.inmo:tgbotapi.libraries.cache.admins.plagubot", version.ref = "tgbotapi-libraries" } plagubot-plugin = { module = "dev.inmo:plagubot.plugin", version.ref = "plagubot" } plagubot-bot = { module = "dev.inmo:plagubot.bot", version.ref = "plagubot" } microutils-repos-common = { module = "dev.inmo:micro_utils.repos.common", version.ref = "microutils" } diff --git a/inlines/build.gradle b/inlines/build.gradle new file mode 100644 index 0000000..89646e6 --- /dev/null +++ b/inlines/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 libs.tgbotapi.admins + } + } + jvmMain { + dependencies { + } + } + } +} diff --git a/inlines/src/commonMain/kotlin/PackageInfo.kt b/inlines/src/commonMain/kotlin/PackageInfo.kt new file mode 100644 index 0000000..848be3b --- /dev/null +++ b/inlines/src/commonMain/kotlin/PackageInfo.kt @@ -0,0 +1 @@ +package dev.inmo.plaguposter.inlines diff --git a/inlines/src/jvmMain/kotlin/Plugin.kt b/inlines/src/jvmMain/kotlin/Plugin.kt new file mode 100644 index 0000000..2152d2f --- /dev/null +++ b/inlines/src/jvmMain/kotlin/Plugin.kt @@ -0,0 +1,67 @@ +package dev.inmo.plaguposter.inlines + +import dev.inmo.micro_utils.pagination.Pagination +import dev.inmo.micro_utils.pagination.utils.paginate +import dev.inmo.plagubot.Plugin +import dev.inmo.plaguposter.common.ChatConfig +import dev.inmo.plaguposter.inlines.models.OfferTemplate +import dev.inmo.plaguposter.inlines.repos.InlineTemplatesRepo +import dev.inmo.tgbotapi.bot.exceptions.RequestException +import dev.inmo.tgbotapi.extensions.api.answers.answerInlineQuery +import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext +import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onBaseInlineQuery +import dev.inmo.tgbotapi.libraries.cache.admins.AdminsCacheAPI +import dev.inmo.tgbotapi.libraries.cache.admins.adminsPlugin +import dev.inmo.tgbotapi.types.inlineQueryAnswerResultsLimit +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 preset: List + ) + override fun Module.setupDI(database: Database, params: JsonObject) { + single { get().decodeFromJsonElement(Config.serializer(), params["inlines"] ?: return@single Config(emptyList())) } + single { InlineTemplatesRepo(getOrNull() ?.preset ?.toMutableSet() ?: mutableSetOf()) } + } + + override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) { + val adminsApi = koin.get() + val chatConfig = koin.get() + val templatesRepo = koin.get() + onBaseInlineQuery { query -> + if (!adminsApi.isAdmin(chatConfig.sourceChatId, query.from.id)) { + answerInlineQuery(query, cachedTime = 0) + return@onBaseInlineQuery + } + val page = query.offset.toIntOrNull() ?: 0 + try { + answerInlineQuery( + query, + templatesRepo.templates.paginate( + Pagination( + page, + inlineQueryAnswerResultsLimit.last + 1 + ) + ).results.mapIndexedNotNull { index, offerTemplate -> + offerTemplate.createArticleResult( + index.toString(), + query.query + ) + }, + nextOffset = (page + 1).toString(), + cachedTime = 0 + ) + } catch (e: RequestException) { + bot.answerInlineQuery( + query, + cachedTime = 0 + ) + } + } + } +} diff --git a/inlines/src/jvmMain/kotlin/models/Format.kt b/inlines/src/jvmMain/kotlin/models/Format.kt new file mode 100644 index 0000000..9b88dbf --- /dev/null +++ b/inlines/src/jvmMain/kotlin/models/Format.kt @@ -0,0 +1,40 @@ +package dev.inmo.plaguposter.inlines.models + +import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputTextMessageContent +import dev.inmo.tgbotapi.types.message.MarkdownV2 +import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient + +@Serializable +data class Format( + val template: String, + val regexTemplate: String = "^$", + val splitBy: String? = null, + val enableMarkdownSupport: Boolean = false +) { + @Transient + val queryRegex = Regex(regexTemplate, RegexOption.DOT_MATCHES_ALL) + + init { + println(queryRegex) + } + + fun formatByRegex(with: String): String? { + return if (queryRegex.matches(with)) { + template.format(*(splitBy ?.let { with.split(it).toTypedArray() } ?: arrayOf(with))) + } else { + null + } + } + + fun createContent(with: String): InputTextMessageContent? { + return if (queryRegex.matches(with)) { + InputTextMessageContent( + template.format(*(splitBy ?.let { with.split(it).toTypedArray() } ?: arrayOf(with))), + if (enableMarkdownSupport) MarkdownV2 else null + ) + } else { + null + } + } +} diff --git a/inlines/src/jvmMain/kotlin/models/OfferTemplate.kt b/inlines/src/jvmMain/kotlin/models/OfferTemplate.kt new file mode 100644 index 0000000..55466d1 --- /dev/null +++ b/inlines/src/jvmMain/kotlin/models/OfferTemplate.kt @@ -0,0 +1,22 @@ +package dev.inmo.plaguposter.inlines.models + +import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.InlineQueryResultArticle +import kotlinx.serialization.Serializable + +@Serializable +data class OfferTemplate( + val title: String, + val formats: List = emptyList(), + val description: String? = null +) { + fun createArticleResult(id: String, query: String): InlineQueryResultArticle? = formats.firstOrNull { + it.queryRegex.matches(query) + } ?.createContent(query) ?.let { content -> + InlineQueryResultArticle( + id, + title, + content, + description = description + ) + } +} diff --git a/inlines/src/jvmMain/kotlin/repos/InlineTemplatesRepo.kt b/inlines/src/jvmMain/kotlin/repos/InlineTemplatesRepo.kt new file mode 100644 index 0000000..57b34d5 --- /dev/null +++ b/inlines/src/jvmMain/kotlin/repos/InlineTemplatesRepo.kt @@ -0,0 +1,16 @@ +package dev.inmo.plaguposter.inlines.repos + +import dev.inmo.plaguposter.inlines.models.OfferTemplate + +class InlineTemplatesRepo( + private val _templates: MutableSet +) { + internal val templates + get() = _templates.toList() + suspend fun addTemplate(offerTemplate: OfferTemplate): Boolean { + return _templates.add(offerTemplate) + } + suspend fun dropTemplate(offerTemplate: OfferTemplate): Boolean { + return _templates.remove(offerTemplate) + } +} diff --git a/inlines/src/main/AndroidManifest.xml b/inlines/src/main/AndroidManifest.xml new file mode 100644 index 0000000..41df2ea --- /dev/null +++ b/inlines/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/posts/build.gradle b/posts/build.gradle index 8ad984c..9f6c3cb 100644 --- a/posts/build.gradle +++ b/posts/build.gradle @@ -11,6 +11,7 @@ kotlin { commonMain { dependencies { api project(":plaguposter.common") + api project(":plaguposter.inlines") } } jvmMain { diff --git a/posts/src/jvmMain/kotlin/Plugin.kt b/posts/src/jvmMain/kotlin/Plugin.kt index 3025093..eacb7d6 100644 --- a/posts/src/jvmMain/kotlin/Plugin.kt +++ b/posts/src/jvmMain/kotlin/Plugin.kt @@ -9,7 +9,10 @@ import dev.inmo.plagubot.Plugin import dev.inmo.plaguposter.common.SuccessfulSymbol import dev.inmo.plaguposter.common.UnsuccessfulSymbol import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo -import dev.inmo.plaguposter.posts.models.ChatConfig +import dev.inmo.plaguposter.common.ChatConfig +import dev.inmo.plaguposter.inlines.models.Format +import dev.inmo.plaguposter.inlines.models.OfferTemplate +import dev.inmo.plaguposter.inlines.repos.InlineTemplatesRepo import dev.inmo.plaguposter.posts.repo.* import dev.inmo.plaguposter.posts.sending.PostPublisher import dev.inmo.tgbotapi.extensions.api.delete @@ -17,9 +20,7 @@ import dev.inmo.tgbotapi.extensions.api.edit.edit import dev.inmo.tgbotapi.extensions.api.send.reply import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand -import dev.inmo.tgbotapi.types.ChatId import dev.inmo.tgbotapi.types.message.textsources.regular -import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.* import org.jetbrains.exposed.sql.Database @@ -87,5 +88,14 @@ object Plugin : Plugin { edit(it, it.content.textSources + regular(SuccessfulSymbol)) } } + + koin.getOrNull() ?.addTemplate( + OfferTemplate( + "Delete post", + listOf( + Format("/delete_post") + ) + ) + ) } } diff --git a/posts_registrar/src/jvmMain/kotlin/Plugin.kt b/posts_registrar/src/jvmMain/kotlin/Plugin.kt index d4fd7c8..9ba9327 100644 --- a/posts_registrar/src/jvmMain/kotlin/Plugin.kt +++ b/posts_registrar/src/jvmMain/kotlin/Plugin.kt @@ -3,7 +3,6 @@ package dev.inmo.plaguposter.posts.registrar import dev.inmo.micro_utils.coroutines.* import dev.inmo.micro_utils.fsm.common.State import dev.inmo.micro_utils.repos.create -import dev.inmo.micro_utils.repos.deleteById import dev.inmo.plagubot.Plugin import dev.inmo.plaguposter.common.* import dev.inmo.plaguposter.posts.models.* @@ -11,7 +10,6 @@ import dev.inmo.plaguposter.posts.registrar.state.RegistrationState import dev.inmo.plaguposter.posts.repo.PostsRepo import dev.inmo.tgbotapi.extensions.api.delete import dev.inmo.tgbotapi.extensions.api.edit.edit -import dev.inmo.tgbotapi.extensions.api.send.reply import dev.inmo.tgbotapi.extensions.api.send.send import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextWithFSM import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.* @@ -22,20 +20,11 @@ import dev.inmo.tgbotapi.extensions.utils.formatting.buildEntities import dev.inmo.tgbotapi.extensions.utils.formatting.regular import dev.inmo.tgbotapi.extensions.utils.mediaGroupMessageOrNull import dev.inmo.tgbotapi.extensions.utils.types.buttons.* -import dev.inmo.tgbotapi.extensions.utils.withContentOrNull -import dev.inmo.tgbotapi.requests.send.SendTextMessage -import dev.inmo.tgbotapi.types.ChatId import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.content.MessageContent -import dev.inmo.tgbotapi.types.message.content.TextContent -import dev.inmo.tgbotapi.types.message.textsources.regular import kotlinx.coroutines.flow.* -import kotlinx.serialization.SerialName 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 @Serializable object Plugin : Plugin { diff --git a/ratings/source/src/jvmMain/kotlin/Plugin.kt b/ratings/source/src/jvmMain/kotlin/Plugin.kt index d20cf8e..cc6f968 100644 --- a/ratings/source/src/jvmMain/kotlin/Plugin.kt +++ b/ratings/source/src/jvmMain/kotlin/Plugin.kt @@ -10,7 +10,6 @@ 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 @@ -19,13 +18,10 @@ 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.* diff --git a/runner/build.gradle b/runner/build.gradle index 2598c11..95abe8a 100644 --- a/runner/build.gradle +++ b/runner/build.gradle @@ -9,6 +9,7 @@ project.version = null dependencies { implementation libs.kotlin api libs.plagubot.bot + api libs.tgbotapi.admins api project(":plaguposter.posts") api project(":plaguposter.posts_registrar") @@ -18,6 +19,7 @@ dependencies { api project(":plaguposter.ratings.source") api project(":plaguposter.ratings.selector") api project(":plaguposter.ratings.gc") + api project(":plaguposter.inlines") api libs.psql } diff --git a/runner/config.json b/runner/config.json index 1fd132b..7906d00 100644 --- a/runner/config.json +++ b/runner/config.json @@ -13,7 +13,9 @@ "dev.inmo.plaguposter.ratings.source.Plugin", "dev.inmo.plaguposter.ratings.selector.Plugin", "dev.inmo.plaguposter.triggers.selector_with_timer.Plugin", - "dev.inmo.plaguposter.ratings.gc.Plugin" + "dev.inmo.plaguposter.ratings.gc.Plugin", + "dev.inmo.tgbotapi.libraries.cache.admins.AdminsPlugin", + "dev.inmo.plaguposter.inlines.Plugin" ], "posts": { "targetChat": 12345678, diff --git a/settings.gradle b/settings.gradle index 6b4cfad..b7a91b9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -10,6 +10,7 @@ String[] includes = [ ":ratings:gc", ":triggers:command", ":triggers:selector_with_timer", + ":inlines", // ":settings", ":runner" ]