mirror of
https://github.com/InsanusMokrassar/PlaguPoster.git
synced 2025-12-05 12:35:39 +00:00
Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0dc459d5dc | |||
| 4024b040e0 | |||
| 74cf8c1a9a | |||
| 82640a0c5d | |||
| 2052d003e5 | |||
| 791a161f8c | |||
| d6bd90267d | |||
| bea7fb7e46 | |||
| 44b2b849e4 | |||
| 8730c67084 | |||
| 3242810ef6 | |||
| 4423eba1d9 | |||
| 1f6dd7aad1 | |||
| 5366dcdba1 | |||
| 18ed638bcc | |||
| 6673b6c69b | |||
| 65f613fd97 | |||
| d605c8c650 | |||
| c47c7b09f4 | |||
| 4c8c93c9f8 | |||
| a3ee0d4c3b | |||
| c8085701d4 | |||
| 2daaf8a6b3 | |||
| 100ee1520f | |||
| 94b3c97efa | |||
| bf8436fa4b | |||
| 5ea80ca1e5 | |||
| a563267da0 | |||
| 4aae1230bc | |||
| 8f29810291 | |||
| 851f3a1c55 | |||
| b398ad43ab | |||
| 1ad7988ae5 | |||
| e114d74c74 | |||
| 6b82879a3e | |||
| c55376da88 | |||
| 6389912b1d | |||
| ad98ca339d | |||
| 3e62eca8ac | |||
| f4e097f7d1 | |||
| 3d5e15d545 | |||
| eef167422e | |||
| 5ae07394dc | |||
| 4ac30cc667 | |||
| 6a43cb32c6 | |||
| e285cc9ec6 | |||
| ceec312208 | |||
| 089be36601 | |||
| af1bddcc85 | |||
| 47f9e09bd2 | |||
| 1d88423b03 | |||
| 3634b9a2a2 | |||
| 4b7c2451cd | |||
| 1cd7c07d29 | |||
| 9c4b49df22 | |||
| 963d33a452 | |||
| 7a05b56af2 | |||
| 39d49f5d58 |
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@@ -12,8 +12,5 @@ jobs:
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Fix android 32.0.0 dx
|
||||
continue-on-error: true
|
||||
run: cd /usr/local/lib/android/sdk/build-tools/32.0.0/ && mv d8 dx && cd lib && mv d8.jar dx.jar
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build
|
||||
|
||||
@@ -7,8 +7,6 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath libs.android.tools.build
|
||||
classpath libs.android.dexcount
|
||||
classpath libs.kotlin.gradle.plugin
|
||||
classpath libs.kotlin.serialization.plugin
|
||||
classpath libs.kotlin.dokka.plugin
|
||||
@@ -20,6 +18,7 @@ allprojects {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
google()
|
||||
maven { url "https://git.inmo.dev/api/packages/InsanusMokrassar/maven" }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package dev.inmo.plaguposter.common
|
||||
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.FullChatIdentifierSerializer
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
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,
|
||||
@Serializable(FullChatIdentifierSerializer::class)
|
||||
val chatId: IdChatIdentifier,
|
||||
val messageId: MessageIdentifier
|
||||
)
|
||||
|
||||
|
||||
20
common/src/jvmMain/kotlin/CommonPlugin.kt
Normal file
20
common/src/jvmMain/kotlin/CommonPlugin.kt
Normal file
@@ -0,0 +1,20 @@
|
||||
package dev.inmo.plaguposter.common
|
||||
|
||||
import dev.inmo.kslog.common.i
|
||||
import dev.inmo.kslog.common.iS
|
||||
import dev.inmo.kslog.common.logger
|
||||
import dev.inmo.plagubot.Plugin
|
||||
import dev.inmo.tgbotapi.extensions.api.chat.get.getChat
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
import org.koin.core.Koin
|
||||
|
||||
object CommonPlugin : Plugin {
|
||||
private val Log = logger
|
||||
override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) {
|
||||
val config = koin.get<ChatConfig>()
|
||||
|
||||
Log.iS { "Target chat info: ${getChat(config.targetChatId)}" }
|
||||
Log.iS { "Source chat info: ${getChat(config.sourceChatId)}" }
|
||||
Log.iS { "Cache chat info: ${getChat(config.cacheChatId)}" }
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
apply plugin: 'com.getkeepsafe.dexcount'
|
||||
|
||||
android {
|
||||
ext {
|
||||
jvmKotlinFolderFile = {
|
||||
String sep = File.separator
|
||||
return new File("${project.projectDir}${sep}src${sep}jvmMain${sep}kotlin")
|
||||
}
|
||||
|
||||
enableIncludingJvmCodeInAndroidPart = {
|
||||
File jvmKotlinFolder = jvmKotlinFolderFile()
|
||||
if (jvmKotlinFolder.exists()) {
|
||||
android.sourceSets.main.java.srcDirs += jvmKotlinFolder.path
|
||||
}
|
||||
}
|
||||
|
||||
disableIncludingJvmCodeInAndroidPart = {
|
||||
File jvmKotlinFolder = jvmKotlinFolderFile()
|
||||
String[] oldDirs = android.sourceSets.main.java.srcDirs
|
||||
android.sourceSets.main.java.srcDirs = []
|
||||
for (oldDir in oldDirs) {
|
||||
if (oldDir != jvmKotlinFolder.path) {
|
||||
android.sourceSets.main.java.srcDirs += oldDir
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compileSdkVersion libs.versions.android.compileSdk.get().toInteger()
|
||||
buildToolsVersion libs.versions.android.buildTools.get()
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion libs.versions.android.minSdk.get().toInteger()
|
||||
targetSdkVersion libs.versions.android.compileSdk.get().toInteger()
|
||||
versionCode "${android_code_version}".toInteger()
|
||||
versionName "$version"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
}
|
||||
debug {
|
||||
debuggable true
|
||||
}
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
exclude 'META-INF/kotlinx-serialization-runtime.kotlin_module'
|
||||
exclude 'META-INF/kotlinx-serialization-cbor.kotlin_module'
|
||||
exclude 'META-INF/kotlinx-serialization-properties.kotlin_module'
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
String sep = File.separator
|
||||
main.java.srcDirs += "src${sep}main${sep}kotlin"
|
||||
}
|
||||
}
|
||||
@@ -10,5 +10,5 @@ android.enableJetifier=true
|
||||
# Project data
|
||||
|
||||
group=dev.inmo
|
||||
version=0.0.3
|
||||
android_code_version=3
|
||||
version=0.0.7
|
||||
android_code_version=7
|
||||
|
||||
@@ -1,27 +1,20 @@
|
||||
[versions]
|
||||
|
||||
kotlin = "1.7.10"
|
||||
kotlin-serialization = "1.4.0"
|
||||
kotlin = "1.7.22"
|
||||
kotlin-serialization = "1.4.1"
|
||||
|
||||
plagubot = "2.3.2"
|
||||
tgbotapi = "3.2.3"
|
||||
microutils = "0.12.13"
|
||||
kslog = "0.5.2"
|
||||
krontab = "0.8.1"
|
||||
tgbotapi-libraries = "0.5.3"
|
||||
plagubot = "3.2.0"
|
||||
tgbotapi = "4.2.1"
|
||||
microutils = "0.16.0"
|
||||
kslog = "0.5.4"
|
||||
krontab = "0.8.4"
|
||||
tgbotapi-libraries = "0.6.5"
|
||||
plagubot-plugins = "0.6.4"
|
||||
|
||||
dokka = "1.7.20"
|
||||
|
||||
psql = "42.5.0"
|
||||
|
||||
dexcount = "3.1.0"
|
||||
junit_version = "4.12"
|
||||
test_ext_junit_version = "1.1.3"
|
||||
espresso_core = "3.4.0"
|
||||
|
||||
android-gradle-plugin = "7.2.2"
|
||||
android-minSdk = "21"
|
||||
android-compileSdk = "32"
|
||||
android-buildTools = "32.0.0"
|
||||
|
||||
[libraries]
|
||||
|
||||
kotlin = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
|
||||
@@ -30,12 +23,12 @@ kotlin-test-common = { module = "org.jetbrains.kotlin:kotlin-test-common", versi
|
||||
kotlin-test-annotations-common = { module = "org.jetbrains.kotlin:kotlin-test-annotations-common", version.ref = "kotlin" }
|
||||
kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" }
|
||||
kotlin-test-js = { module = "org.jetbrains.kotlin:kotlin-test-js", version.ref = "kotlin" }
|
||||
android-test-junit = { module = "androidx.test.ext:junit", version.ref = "test_ext_junit_version" }
|
||||
android-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso_core" }
|
||||
|
||||
tgbotapi = { module = "dev.inmo:tgbotapi", version.ref = "tgbotapi" }
|
||||
plagubot-plugin = { module = "dev.inmo:plagubot.plugin", version.ref = "plagubot" }
|
||||
plagubot-bot = { module = "dev.inmo:plagubot.bot", version.ref = "plagubot" }
|
||||
plagubot-plugins-inline-queries = { module = "dev.inmo:plagubot.plugins.inline.queries", version.ref = "plagubot-plugins" }
|
||||
plagubot-plugins-inline-buttons = { module = "dev.inmo:plagubot.plugins.inline.buttons", version.ref = "plagubot-plugins" }
|
||||
microutils-repos-common = { module = "dev.inmo:micro_utils.repos.common", version.ref = "microutils" }
|
||||
microutils-repos-exposed = { module = "dev.inmo:micro_utils.repos.exposed", version.ref = "microutils" }
|
||||
microutils-repos-cache = { module = "dev.inmo:micro_utils.repos.cache", version.ref = "microutils" }
|
||||
@@ -47,11 +40,9 @@ psql = { module = "org.postgresql:postgresql", version.ref = "psql" }
|
||||
|
||||
# buildscript classpaths
|
||||
|
||||
android-tools-build = { module = "com.android.tools.build:gradle", version.ref = "android-gradle-plugin" }
|
||||
android-dexcount = { module = "com.getkeepsafe.dexcount:dexcount-gradle-plugin", version.ref = "dexcount" }
|
||||
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 = "kotlin" }
|
||||
kotlin-dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" }
|
||||
|
||||
[plugins]
|
||||
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
@@ -15,6 +14,7 @@ kotlin {
|
||||
}
|
||||
jvmMain {
|
||||
dependencies {
|
||||
api libs.plagubot.plugins.inline.queries
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
package dev.inmo.plaguposter.inlines
|
||||
package dev.inmo.plagubot.plugins.inline.queries
|
||||
|
||||
@@ -1,81 +1,29 @@
|
||||
package dev.inmo.plaguposter.inlines
|
||||
|
||||
import dev.inmo.micro_utils.pagination.Pagination
|
||||
import dev.inmo.micro_utils.pagination.utils.paginate
|
||||
import dev.inmo.kslog.common.TagLogger
|
||||
import dev.inmo.kslog.common.w
|
||||
import dev.inmo.plagubot.Plugin
|
||||
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.tgbotapi.bot.exceptions.RequestException
|
||||
import dev.inmo.tgbotapi.extensions.api.answers.answerInlineQuery
|
||||
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.onBaseInlineQuery
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
|
||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.*
|
||||
import dev.inmo.tgbotapi.types.inlineQueryAnswerResultsLimit
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.*
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
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<OfferTemplate>
|
||||
)
|
||||
private val actualPlugin = dev.inmo.plagubot.plugins.inline.queries.Plugin
|
||||
|
||||
object Plugin : Plugin by actualPlugin {
|
||||
private val log = TagLogger("InlinePlugin")
|
||||
|
||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
||||
single { get<Json>().decodeFromJsonElement(Config.serializer(), params["inlines"] ?: return@single Config(emptyList())) }
|
||||
single { InlineTemplatesRepo(getOrNull<Config>() ?.preset ?.toMutableSet() ?: mutableSetOf()) }
|
||||
single { actualPlugin }
|
||||
}
|
||||
|
||||
override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) {
|
||||
val templatesRepo = koin.get<InlineTemplatesRepo>()
|
||||
onBaseInlineQuery { query ->
|
||||
val page = query.offset.toIntOrNull() ?: 0
|
||||
val queryString = query.query.trim()
|
||||
try {
|
||||
answerInlineQuery(
|
||||
query,
|
||||
templatesRepo.templates.paginate(
|
||||
Pagination(
|
||||
page,
|
||||
inlineQueryAnswerResultsLimit.last + 1
|
||||
)
|
||||
).results.mapIndexedNotNull { index, offerTemplate ->
|
||||
offerTemplate.createArticleResult(
|
||||
index.toString(),
|
||||
queryString
|
||||
)
|
||||
},
|
||||
nextOffset = (page + 1).toString(),
|
||||
cachedTime = 0
|
||||
)
|
||||
} catch (e: RequestException) {
|
||||
bot.answerInlineQuery(
|
||||
query,
|
||||
cachedTime = 0
|
||||
)
|
||||
}
|
||||
log.w {
|
||||
"Built-in inline plugin has been deprecated. Use \"${actualPlugin::class.qualifiedName}\" instead"
|
||||
}
|
||||
onCommand("help", requireOnlyCommandInMessage = true) {
|
||||
reply(
|
||||
it,
|
||||
"Push the button above to see available commands",
|
||||
replyMarkup = flatInlineKeyboard {
|
||||
inlineQueryInCurrentChatButton("Toggle commands", "")
|
||||
}
|
||||
)
|
||||
}
|
||||
koin.getOrNull<InlineTemplatesRepo>() ?.apply {
|
||||
addTemplate(
|
||||
OfferTemplate(
|
||||
"Trigger help button",
|
||||
listOf(Format("/help"))
|
||||
)
|
||||
)
|
||||
with(actualPlugin) {
|
||||
setupBotPlugin(koin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
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<Format> = 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
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package dev.inmo.plaguposter.inlines.repos
|
||||
|
||||
import dev.inmo.plaguposter.inlines.models.OfferTemplate
|
||||
|
||||
class InlineTemplatesRepo(
|
||||
private val _templates: MutableSet<OfferTemplate>
|
||||
) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
<manifest package="dev.inmo.plaguposter.inlines"/>
|
||||
<manifest package="dev.inmo.plagubot.plugins.inline.queries"/>
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
project.version = "$version"
|
||||
project.group = "$group"
|
||||
|
||||
// apply from: "$publishGradlePath"
|
||||
|
||||
kotlin {
|
||||
android {
|
||||
publishAllLibraryVariants()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
implementation libs.kotlin
|
||||
api libs.kotlin.serialization
|
||||
}
|
||||
}
|
||||
commonTest {
|
||||
dependencies {
|
||||
implementation libs.kotlin.test.common
|
||||
implementation libs.kotlin.test.annotations.common
|
||||
}
|
||||
}
|
||||
androidTest {
|
||||
dependencies {
|
||||
implementation libs.kotlin.test.junit
|
||||
implementation libs.android.test.junit
|
||||
implementation libs.android.test.espresso.core
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply from: "$defaultAndroidSettingsPresetPath"
|
||||
@@ -4,21 +4,12 @@ project.group = "$group"
|
||||
// apply from: "$publishGradlePath"
|
||||
|
||||
kotlin {
|
||||
jvm {
|
||||
compilations.main {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
}
|
||||
jvm()
|
||||
js (IR) {
|
||||
browser()
|
||||
nodejs()
|
||||
}
|
||||
android {
|
||||
publishAllLibraryVariants()
|
||||
}
|
||||
|
||||
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
@@ -43,19 +34,7 @@ kotlin {
|
||||
implementation libs.kotlin.test.junit
|
||||
}
|
||||
}
|
||||
androidTest {
|
||||
dependencies {
|
||||
implementation libs.kotlin.test.junit
|
||||
implementation libs.android.test.junit
|
||||
implementation libs.android.test.espresso.core
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
apply from: "$defaultAndroidSettingsPresetPath"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
@@ -15,5 +14,10 @@ kotlin {
|
||||
api libs.microutils.koin
|
||||
}
|
||||
}
|
||||
jvmMain {
|
||||
dependencies {
|
||||
api libs.plagubot.plugins.inline.queries
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,21 @@ package dev.inmo.plaguposter.posts.panel
|
||||
import dev.inmo.plaguposter.posts.models.RegisteredPost
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.InlineKeyboardButton
|
||||
|
||||
fun interface PanelButtonBuilder {
|
||||
interface PanelButtonBuilder {
|
||||
val weight: Int
|
||||
suspend fun buildButton(post: RegisteredPost): InlineKeyboardButton?
|
||||
|
||||
class Default(override val weight: Int = 0, private val block: suspend (RegisteredPost) -> InlineKeyboardButton?) : PanelButtonBuilder {
|
||||
override suspend fun buildButton(post: RegisteredPost): InlineKeyboardButton? = block(post)
|
||||
}
|
||||
|
||||
companion object {
|
||||
operator fun invoke(block: suspend (RegisteredPost) -> InlineKeyboardButton?) = Default(
|
||||
block = block
|
||||
)
|
||||
operator fun invoke(weight: Int, block: suspend (RegisteredPost) -> InlineKeyboardButton?) = Default(
|
||||
weight,
|
||||
block
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@ import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineK
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
|
||||
class PanelButtonsAPI(
|
||||
private val preset: List<PanelButtonBuilder>,
|
||||
private val preset: Map<Int, List<PanelButtonBuilder>>,
|
||||
private val rootPanelButtonText: String
|
||||
) {
|
||||
private val _buttons = mutableSetOf<PanelButtonBuilder>().also {
|
||||
it.addAll(preset)
|
||||
private val _buttonsMap = mutableMapOf<Int, MutableList<PanelButtonBuilder>>().also {
|
||||
it.putAll(preset.map { it.key to it.value.toMutableList() })
|
||||
}
|
||||
internal val buttonsBuilders: List<PanelButtonBuilder>
|
||||
get() = _buttons.toList()
|
||||
get() = _buttonsMap.toList().sortedBy { it.first }.flatMap { it.second }
|
||||
internal val forceRefreshFlow = MutableSharedFlow<PostId>()
|
||||
|
||||
val RootPanelButtonBuilder = PanelButtonBuilder {
|
||||
@@ -22,8 +22,13 @@ class PanelButtonsAPI(
|
||||
)
|
||||
}
|
||||
|
||||
fun add(button: PanelButtonBuilder) = _buttons.add(button)
|
||||
fun remove(button: PanelButtonBuilder) = _buttons.remove(button)
|
||||
fun add(button: PanelButtonBuilder, weight: Int = button.weight) = _buttonsMap.getOrPut(weight) { mutableListOf() }.add(button)
|
||||
fun remove(button: PanelButtonBuilder) = _buttonsMap.mapNotNull { (k, v) ->
|
||||
v.remove(button)
|
||||
k.takeIf { v.isEmpty() }
|
||||
}.forEach {
|
||||
_buttonsMap.remove(it)
|
||||
}
|
||||
suspend fun forceRefresh(postId: PostId) {
|
||||
forceRefreshFlow.emit(postId)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
package dev.inmo.plaguposter.posts.panel
|
||||
|
||||
import com.benasher44.uuid.uuid4
|
||||
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.deleteById
|
||||
import dev.inmo.micro_utils.repos.id
|
||||
import dev.inmo.micro_utils.repos.set
|
||||
import dev.inmo.micro_utils.repos.unset
|
||||
import dev.inmo.micro_utils.repos.value
|
||||
import dev.inmo.plagubot.Plugin
|
||||
import dev.inmo.plaguposter.common.ChatConfig
|
||||
import dev.inmo.plaguposter.common.UnsuccessfulSymbol
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.plaguposter.posts.panel.repos.PostsMessages
|
||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||
@@ -14,18 +19,23 @@ import dev.inmo.tgbotapi.extensions.api.answers.answer
|
||||
import dev.inmo.tgbotapi.extensions.api.delete
|
||||
import dev.inmo.tgbotapi.extensions.api.edit.edit
|
||||
import dev.inmo.tgbotapi.extensions.api.edit.text.editMessageText
|
||||
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.expectations.waitMessageDataCallbackQuery
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.command
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onMessageDataCallbackQuery
|
||||
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.ChatId
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.message.ParseMode
|
||||
import dev.inmo.tgbotapi.utils.bold
|
||||
import dev.inmo.tgbotapi.utils.buildEntities
|
||||
import dev.inmo.tgbotapi.utils.italic
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.*
|
||||
@@ -40,7 +50,7 @@ object Plugin : Plugin {
|
||||
val parseMode: ParseMode? = null,
|
||||
val buttonsPerRow: Int = 4,
|
||||
val deleteButtonText: String? = null,
|
||||
val rootButtonText: String = "\uD83D\uDD19",
|
||||
val rootButtonText: String = "◀️",
|
||||
val refreshButtonText: String? = "\uD83D\uDD04"
|
||||
)
|
||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
||||
@@ -68,9 +78,13 @@ object Plugin : Plugin {
|
||||
}
|
||||
)
|
||||
PanelButtonsAPI(
|
||||
getAllDistinct<PanelButtonBuilder>() + builtInButtons,
|
||||
emptyMap(),
|
||||
config.rootButtonText
|
||||
)
|
||||
).apply {
|
||||
(getAllDistinct<PanelButtonBuilder>() + builtInButtons).forEach {
|
||||
add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +121,7 @@ object Plugin : Plugin {
|
||||
|
||||
suspend fun refreshPostMessage(
|
||||
postId: PostId,
|
||||
chatId: ChatId,
|
||||
chatId: IdChatIdentifier,
|
||||
messageId: MessageIdentifier
|
||||
) {
|
||||
val post = postsRepo.getById(postId) ?: return
|
||||
@@ -131,6 +145,7 @@ object Plugin : Plugin {
|
||||
) {
|
||||
val postId = it.data.removePrefix(PanelButtonsAPI.openGlobalMenuDataPrefix).let(::PostId)
|
||||
refreshPostMessage(postId, it.message.chat.id, it.message.messageId)
|
||||
answer(it)
|
||||
}
|
||||
onMessageDataCallbackQuery(
|
||||
initialFilter = {
|
||||
@@ -167,11 +182,13 @@ object Plugin : Plugin {
|
||||
val postId = query.data.removePrefix("refresh ").let(::PostId)
|
||||
val (chatId, messageId) = postsMessages.get(postId) ?: return@onMessageDataCallbackQuery
|
||||
|
||||
refreshPostMessage(
|
||||
postId,
|
||||
chatId,
|
||||
messageId
|
||||
)
|
||||
runCatchingSafely {
|
||||
refreshPostMessage(
|
||||
postId,
|
||||
chatId,
|
||||
messageId
|
||||
)
|
||||
}
|
||||
answer(query)
|
||||
}
|
||||
|
||||
@@ -179,5 +196,59 @@ object Plugin : Plugin {
|
||||
val (chatId, messageId) = postsMessages.get(it) ?: return@subscribeSafelyWithoutExceptions
|
||||
refreshPostMessage(it, chatId, messageId)
|
||||
}
|
||||
|
||||
command("panel") {
|
||||
val reply = it.replyTo
|
||||
|
||||
if (reply == null) {
|
||||
runCatchingSafely {
|
||||
edit(
|
||||
it,
|
||||
it.content.textSources + buildEntities {
|
||||
+"${UnsuccessfulSymbol}\n" + bold("Result") + ": " + italic("You should reply post content to trigger panel retrieving")
|
||||
}
|
||||
)
|
||||
}.onFailure { _ ->
|
||||
reply(
|
||||
it,
|
||||
buildEntities {
|
||||
bold("Result") + ": " + italic("You should reply post content to trigger panel retrieving")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return@command
|
||||
}
|
||||
|
||||
val postId = postsRepo.getIdByChatAndMessage(reply.chat.id, reply.messageId)
|
||||
if (postId == null) {
|
||||
runCatchingSafely {
|
||||
edit(
|
||||
it,
|
||||
it.content.textSources + buildEntities {
|
||||
+"${UnsuccessfulSymbol}\n" + bold("Result") + ": " + italic("Unable to find post related to replied message")
|
||||
}
|
||||
)
|
||||
}.onFailure { _ ->
|
||||
reply(
|
||||
it,
|
||||
buildEntities {
|
||||
bold("Result") + ": " + italic("Unable to find post related to replied message")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return@command
|
||||
}
|
||||
|
||||
postsMessages.get(postId) ?.let {
|
||||
runCatchingSafely { delete(it.id, it.value) }
|
||||
postsMessages.unset(postId)
|
||||
}
|
||||
|
||||
refreshPostMessage(postId, it.chat.id, it.messageId)
|
||||
|
||||
postsMessages.set(postId, it.chat.id to it.messageId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,18 +5,20 @@ import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo
|
||||
import dev.inmo.micro_utils.repos.mappers.withMapper
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.FullChatIdentifierSerializer
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
import kotlinx.serialization.builtins.PairSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
|
||||
private val ChatIdToMessageSerializer = PairSerializer(ChatId.serializer(), MessageIdentifier.serializer())
|
||||
private val ChatIdToMessageSerializer = PairSerializer(FullChatIdentifierSerializer, MessageIdentifier.serializer())
|
||||
|
||||
fun PostsMessages(
|
||||
database: Database,
|
||||
json: Json
|
||||
): KeyValueRepo<PostId, Pair<ChatId, MessageIdentifier>> = ExposedKeyValueRepo<String, String>(
|
||||
): KeyValueRepo<PostId, Pair<IdChatIdentifier, MessageIdentifier>> = ExposedKeyValueRepo<String, String>(
|
||||
database,
|
||||
{ text("postId") },
|
||||
{ text("chatToMessage") },
|
||||
@@ -25,5 +27,5 @@ fun PostsMessages(
|
||||
{ string },
|
||||
{ json.encodeToString(ChatIdToMessageSerializer, this) },
|
||||
{ PostId(this) },
|
||||
{ json.decodeFromString(ChatIdToMessageSerializer, this) }
|
||||
{ json.decodeFromString(ChatIdToMessageSerializer, this).let { (it.first as IdChatIdentifier) to it.second } }
|
||||
)
|
||||
|
||||
@@ -1,25 +1,39 @@
|
||||
package dev.inmo.plaguposter.posts.models
|
||||
|
||||
import dev.inmo.tgbotapi.extensions.utils.mediaGroupMessageOrNull
|
||||
import dev.inmo.tgbotapi.extensions.utils.possiblyMediaGroupMessageOrNull
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.FullChatIdentifierSerializer
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.content.MessageContent
|
||||
import dev.inmo.tgbotapi.types.message.content.MediaGroupContent
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class PostContentInfo(
|
||||
val chatId: ChatId,
|
||||
@Serializable(FullChatIdentifierSerializer::class)
|
||||
val chatId: IdChatIdentifier,
|
||||
val messageId: MessageIdentifier,
|
||||
val group: String?,
|
||||
val order: Int
|
||||
) {
|
||||
companion object {
|
||||
fun fromMessage(message: ContentMessage<*>, order: Int) = PostContentInfo(
|
||||
private fun fromMessage(message: ContentMessage<*>, order: Int) = PostContentInfo(
|
||||
message.chat.id,
|
||||
message.messageId,
|
||||
message.mediaGroupMessageOrNull() ?.mediaGroupId,
|
||||
message.possiblyMediaGroupMessageOrNull() ?.mediaGroupId,
|
||||
order
|
||||
)
|
||||
fun fromMessage(message: ContentMessage<*>): List<PostContentInfo> {
|
||||
val content = message.content
|
||||
|
||||
return if (content is MediaGroupContent<*>) {
|
||||
content.group.mapIndexed { i, it ->
|
||||
fromMessage(it.sourceMessage, i)
|
||||
}
|
||||
} else {
|
||||
listOf(fromMessage(message, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@ import com.soywiz.klock.DateTime
|
||||
import dev.inmo.micro_utils.repos.ReadCRUDRepo
|
||||
import dev.inmo.plaguposter.posts.models.*
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
|
||||
interface ReadPostsRepo : ReadCRUDRepo<RegisteredPost, PostId> {
|
||||
suspend fun getIdByChatAndMessage(chatId: ChatId, messageId: MessageIdentifier): PostId?
|
||||
suspend fun getIdByChatAndMessage(chatId: IdChatIdentifier, messageId: MessageIdentifier): PostId?
|
||||
suspend fun getPostCreationTime(postId: PostId): DateTime?
|
||||
suspend fun getFirstMessageInfo(postId: PostId): PostContentInfo?
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import dev.inmo.tgbotapi.extensions.api.send.send
|
||||
import dev.inmo.tgbotapi.extensions.utils.*
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.message.content.MediaGroupContent
|
||||
import dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent
|
||||
|
||||
class PostPublisher(
|
||||
private val bot: TelegramBot,
|
||||
@@ -37,14 +38,26 @@ class PostPublisher(
|
||||
|
||||
sortedMessagesContents.forEach { (_, contents) ->
|
||||
contents.singleOrNull() ?.also {
|
||||
bot.copyMessage(targetChatId, it.chatId, it.messageId)
|
||||
runCatching {
|
||||
bot.copyMessage(targetChatId, it.chatId, it.messageId)
|
||||
}.onFailure { _ ->
|
||||
runCatching {
|
||||
bot.forwardMessage(
|
||||
it.chatId,
|
||||
targetChatId,
|
||||
it.messageId
|
||||
)
|
||||
}.onSuccess {
|
||||
bot.copyMessage(targetChatId, it)
|
||||
}
|
||||
}
|
||||
return@forEach
|
||||
}
|
||||
val resultContents = contents.mapNotNull {
|
||||
it.order to (bot.forwardMessage(toChatId = cachingChatId, fromChatId = it.chatId, messageId = it.messageId).contentMessageOrNull() ?: return@mapNotNull null)
|
||||
}.sortedBy { it.first }.mapNotNull { (_, it) ->
|
||||
it.withContentOrNull<MediaGroupContent>() ?: null.also { _ ->
|
||||
bot.copyMessage(targetChatId, it)
|
||||
}.sortedBy { it.first }.mapNotNull { (_, forwardedMessage) ->
|
||||
forwardedMessage.withContentOrNull<MediaGroupPartContent>() ?: null.also { _ ->
|
||||
bot.copyMessage(targetChatId, forwardedMessage)
|
||||
}
|
||||
}
|
||||
resultContents.singleOrNull() ?.also {
|
||||
|
||||
@@ -10,9 +10,9 @@ import dev.inmo.plaguposter.common.SuccessfulSymbol
|
||||
import dev.inmo.plaguposter.common.UnsuccessfulSymbol
|
||||
import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo
|
||||
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.plagubot.plugins.inline.queries.models.Format
|
||||
import dev.inmo.plagubot.plugins.inline.queries.models.OfferTemplate
|
||||
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
||||
import dev.inmo.plaguposter.posts.repo.*
|
||||
import dev.inmo.plaguposter.posts.sending.PostPublisher
|
||||
import dev.inmo.tgbotapi.extensions.api.delete
|
||||
|
||||
@@ -5,6 +5,7 @@ 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.ChatId
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
import org.jetbrains.exposed.sql.*
|
||||
|
||||
internal class ExposedContentInfoRepo(
|
||||
@@ -13,13 +14,14 @@ internal class ExposedContentInfoRepo(
|
||||
) : ExposedRepo, Table(name = "posts_content") {
|
||||
val postIdColumn = text("post_id").references(postIdColumnReference, ReferenceOption.CASCADE, ReferenceOption.CASCADE)
|
||||
val chatIdColumn = long("chat_id")
|
||||
val threadIdColumn = long("thread_id").nullable().default(null)
|
||||
val messageIdColumn = long("message_id")
|
||||
val groupColumn = text("group").nullable()
|
||||
val orderColumn = integer("order")
|
||||
|
||||
val ResultRow.asObject
|
||||
get() = PostContentInfo(
|
||||
ChatId(get(chatIdColumn)),
|
||||
IdChatIdentifier(get(chatIdColumn), get(threadIdColumn)),
|
||||
get(messageIdColumn),
|
||||
get(groupColumn),
|
||||
get(orderColumn)
|
||||
|
||||
@@ -3,17 +3,20 @@ package dev.inmo.plaguposter.posts.exposed
|
||||
import com.benasher44.uuid.uuid4
|
||||
import com.soywiz.klock.DateTime
|
||||
import dev.inmo.micro_utils.repos.KeyValuesRepo
|
||||
import dev.inmo.micro_utils.repos.UpdatedValuePair
|
||||
import dev.inmo.micro_utils.repos.exposed.AbstractExposedCRUDRepo
|
||||
import dev.inmo.micro_utils.repos.exposed.initTable
|
||||
import dev.inmo.plaguposter.posts.models.*
|
||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.statements.InsertStatement
|
||||
import org.jetbrains.exposed.sql.statements.UpdateStatement
|
||||
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
|
||||
|
||||
class ExposedPostsRepo(
|
||||
@@ -21,7 +24,7 @@ class ExposedPostsRepo(
|
||||
) : PostsRepo, AbstractExposedCRUDRepo<RegisteredPost, PostId, NewPost>(
|
||||
tableName = "posts"
|
||||
) {
|
||||
val idColumn = text("id").clientDefault { uuid4().toString() }
|
||||
val idColumn = text("id")
|
||||
val createdColumn = double("datetime").default(0.0)
|
||||
|
||||
private val contentRepo by lazy {
|
||||
@@ -33,11 +36,13 @@ class ExposedPostsRepo(
|
||||
|
||||
override val primaryKey: PrimaryKey = PrimaryKey(idColumn)
|
||||
|
||||
override val selectById: SqlExpressionBuilder.(PostId) -> Op<Boolean> = { idColumn.eq(it.string) }
|
||||
override val selectByIds: SqlExpressionBuilder.(List<PostId>) -> Op<Boolean> = { idColumn.inList(it.map { it.string }) }
|
||||
override val selectById: ISqlExpressionBuilder.(PostId) -> Op<Boolean> = { idColumn.eq(it.string) }
|
||||
override val selectByIds: ISqlExpressionBuilder.(List<PostId>) -> Op<Boolean> = { idColumn.inList(it.map { it.string }) }
|
||||
override val ResultRow.asId: PostId
|
||||
get() = PostId(get(idColumn))
|
||||
override val ResultRow.asObject: RegisteredPost
|
||||
get() {
|
||||
val id = PostId(get(idColumn))
|
||||
val id = asId
|
||||
return RegisteredPost(
|
||||
id,
|
||||
DateTime(get(createdColumn)),
|
||||
@@ -59,18 +64,6 @@ class ExposedPostsRepo(
|
||||
override fun InsertStatement<Number>.asObject(value: NewPost): RegisteredPost {
|
||||
val id = PostId(get(idColumn))
|
||||
|
||||
with(contentRepo) {
|
||||
value.content.forEach { contentInfo ->
|
||||
insert {
|
||||
it[postIdColumn] = id.string
|
||||
it[chatIdColumn] = contentInfo.chatId.chatId
|
||||
it[messageIdColumn] = contentInfo.messageId
|
||||
it[groupColumn] = contentInfo.group
|
||||
it[orderColumn] = contentInfo.order
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return RegisteredPost(
|
||||
id,
|
||||
DateTime(get(createdColumn)),
|
||||
@@ -82,25 +75,53 @@ class ExposedPostsRepo(
|
||||
)
|
||||
}
|
||||
|
||||
override fun update(id: PostId, value: NewPost, it: UpdateStatement) {
|
||||
with(contentRepo) {
|
||||
deleteWhere { postIdColumn.eq(id.string) }
|
||||
value.content.forEach { contentInfo ->
|
||||
insert {
|
||||
it[postIdColumn] = id.string
|
||||
it[chatIdColumn] = contentInfo.chatId.chatId
|
||||
it[messageIdColumn] = contentInfo.messageId
|
||||
it[groupColumn] = contentInfo.group
|
||||
it[orderColumn] = contentInfo.order
|
||||
override fun createAndInsertId(value: NewPost, it: InsertStatement<Number>): PostId {
|
||||
val id = PostId(uuid4().toString())
|
||||
it[idColumn] = id.string
|
||||
return id
|
||||
}
|
||||
|
||||
override fun update(id: PostId?, value: NewPost, it: UpdateBuilder<Int>) {}
|
||||
|
||||
private fun updateContent(post: RegisteredPost) {
|
||||
transaction(database) {
|
||||
with(contentRepo) {
|
||||
deleteWhere { postIdColumn.eq(post.id.string) }
|
||||
post.content.forEach { contentInfo ->
|
||||
insert {
|
||||
it[postIdColumn] = post.id.string
|
||||
it[chatIdColumn] = contentInfo.chatId.chatId
|
||||
it[threadIdColumn] = contentInfo.chatId.threadId
|
||||
it[messageIdColumn] = contentInfo.messageId
|
||||
it[groupColumn] = contentInfo.group
|
||||
it[orderColumn] = contentInfo.order
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun insert(value: NewPost, it: InsertStatement<Number>) {
|
||||
super.insert(value, it)
|
||||
it[createdColumn] = DateTime.now().unixMillis
|
||||
}
|
||||
|
||||
override suspend fun onAfterCreate(values: List<Pair<NewPost, RegisteredPost>>): List<RegisteredPost> {
|
||||
return values.map {
|
||||
val actual = it.second.copy(content = it.first.content)
|
||||
updateContent(actual)
|
||||
actual
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun onAfterUpdate(value: List<UpdatedValuePair<NewPost, RegisteredPost>>): List<RegisteredPost> {
|
||||
return value.map {
|
||||
val actual = it.second.copy(content = it.first.content)
|
||||
updateContent(actual)
|
||||
actual
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun deleteById(ids: List<PostId>) {
|
||||
onBeforeDelete(ids)
|
||||
val posts = ids.mapNotNull {
|
||||
@@ -109,7 +130,7 @@ class ExposedPostsRepo(
|
||||
val existsIds = posts.keys.toList()
|
||||
transaction(db = database) {
|
||||
val deleted = deleteWhere(null, null) {
|
||||
selectByIds(existsIds)
|
||||
selectByIds(it, existsIds)
|
||||
}
|
||||
with(contentRepo) {
|
||||
deleteWhere {
|
||||
@@ -129,10 +150,14 @@ class ExposedPostsRepo(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getIdByChatAndMessage(chatId: ChatId, messageId: MessageIdentifier): PostId? {
|
||||
override suspend fun getIdByChatAndMessage(chatId: IdChatIdentifier, messageId: MessageIdentifier): PostId? {
|
||||
return transaction(database) {
|
||||
with(contentRepo) {
|
||||
select { chatIdColumn.eq(chatId.chatId).and(messageIdColumn.eq(messageId)) }.limit(1).firstOrNull() ?.get(postIdColumn)
|
||||
select {
|
||||
chatIdColumn.eq(chatId.chatId)
|
||||
.and(chatId.threadId ?.let { threadIdColumn.eq(it) } ?: threadIdColumn.isNull())
|
||||
.and(messageIdColumn.eq(messageId))
|
||||
}.limit(1).firstOrNull() ?.get(postIdColumn)
|
||||
} ?.let(::PostId)
|
||||
}
|
||||
}
|
||||
@@ -140,4 +165,10 @@ class ExposedPostsRepo(
|
||||
override suspend fun getPostCreationTime(postId: PostId): DateTime? = transaction(database) {
|
||||
select { selectById(postId) }.limit(1).firstOrNull() ?.get(createdColumn) ?.let(::DateTime)
|
||||
}
|
||||
|
||||
override suspend fun getFirstMessageInfo(postId: PostId): PostContentInfo? = transaction(database) {
|
||||
with(contentRepo) {
|
||||
select { postIdColumn.eq(postId.string) }.limit(1).firstOrNull() ?.asObject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
@@ -13,9 +12,5 @@ kotlin {
|
||||
api project(":plaguposter.posts")
|
||||
}
|
||||
}
|
||||
jvmMain {
|
||||
dependencies {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,20 +3,24 @@ package dev.inmo.plaguposter.posts.registrar.state
|
||||
import dev.inmo.micro_utils.fsm.common.State
|
||||
import dev.inmo.plaguposter.posts.models.PostContentInfo
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.FullChatIdentifierSerializer
|
||||
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
interface RegistrationState : State {
|
||||
override val context: ChatId
|
||||
override val context: IdChatIdentifier
|
||||
|
||||
@Serializable
|
||||
data class InProcess(
|
||||
override val context: ChatId,
|
||||
@Serializable(FullChatIdentifierSerializer::class)
|
||||
override val context: IdChatIdentifier,
|
||||
val messages: List<PostContentInfo>
|
||||
) : RegistrationState
|
||||
|
||||
@Serializable
|
||||
data class Finish(
|
||||
override val context: ChatId,
|
||||
@Serializable(FullChatIdentifierSerializer::class)
|
||||
override val context: IdChatIdentifier,
|
||||
val messages: List<PostContentInfo>
|
||||
) : RegistrationState
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ 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.*
|
||||
import dev.inmo.plaguposter.inlines.models.Format
|
||||
import dev.inmo.plaguposter.inlines.models.OfferTemplate
|
||||
import dev.inmo.plaguposter.inlines.repos.InlineTemplatesRepo
|
||||
import dev.inmo.plagubot.plugins.inline.queries.models.Format
|
||||
import dev.inmo.plagubot.plugins.inline.queries.models.OfferTemplate
|
||||
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
||||
import dev.inmo.plaguposter.posts.models.*
|
||||
import dev.inmo.plaguposter.posts.registrar.state.RegistrationState
|
||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||
@@ -18,13 +18,16 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextWithFSM
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.*
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.strictlyOn
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.raw.text
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.sameChat
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.sameMessage
|
||||
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.textContentOrNull
|
||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.*
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.content.MediaGroupContent
|
||||
import dev.inmo.tgbotapi.types.message.content.MessageContent
|
||||
import dev.inmo.tgbotapi.utils.regular
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.koin.core.Koin
|
||||
@@ -40,7 +43,7 @@ object Plugin : Plugin {
|
||||
|
||||
val messageToDelete = send(
|
||||
state.context,
|
||||
buildEntities {
|
||||
dev.inmo.tgbotapi.utils.buildEntities {
|
||||
if (state.messages.isNotEmpty()) {
|
||||
regular("Your message(s) has been registered. You may send new ones or push \"Finish\" to finalize your post")
|
||||
} else {
|
||||
@@ -62,32 +65,31 @@ object Plugin : Plugin {
|
||||
val newMessagesInfo = firstOf {
|
||||
add {
|
||||
listOf(
|
||||
waitContentMessage(
|
||||
includeMediaGroups = false
|
||||
).filter {
|
||||
it.chat.id == state.context
|
||||
waitContentMessage().filter {
|
||||
it.chat.id == state.context && it.content.textContentOrNull() ?.text != "/finish_post"
|
||||
}.take(1).first()
|
||||
)
|
||||
}
|
||||
add {
|
||||
waitMediaGroupMessages().filter {
|
||||
it.first().chat.id == state.context
|
||||
}.take(1).first()
|
||||
}
|
||||
add {
|
||||
val finishPressed = waitMessageDataCallbackQuery().filter {
|
||||
it.message.sameMessage(messageToDelete) && it.data == buttonUuid
|
||||
}.first()
|
||||
emptyList<ContentMessage<MessageContent>>()
|
||||
}
|
||||
add {
|
||||
val finishPressed = waitTextMessage().filter {
|
||||
it.sameChat(messageToDelete) && it.content.text == "/finish_post"
|
||||
}.first()
|
||||
emptyList<ContentMessage<MessageContent>>()
|
||||
}
|
||||
}.ifEmpty {
|
||||
edit(messageToDelete, "Ok, finishing your request")
|
||||
return@strictlyOn RegistrationState.Finish(
|
||||
state.context,
|
||||
state.messages
|
||||
)
|
||||
}.map {
|
||||
PostContentInfo.fromMessage(it, state.messages.size)
|
||||
}.flatMap {
|
||||
PostContentInfo.fromMessage(it)
|
||||
}
|
||||
|
||||
RegistrationState.InProcess(
|
||||
@@ -112,31 +114,23 @@ object Plugin : Plugin {
|
||||
}
|
||||
|
||||
onContentMessage(
|
||||
initialFilter = { it.chat.id == config.sourceChatId && it.mediaGroupMessageOrNull() ?.mediaGroupId == null && !FirstSourceIsCommandsFilter(it) }
|
||||
initialFilter = { it.chat.id == config.sourceChatId && !FirstSourceIsCommandsFilter(it) }
|
||||
) {
|
||||
startChain(RegistrationState.Finish(it.chat.id, listOf(PostContentInfo.fromMessage(it, 0))))
|
||||
}
|
||||
|
||||
onMediaGroup(
|
||||
initialFilter = { it.first().chat.id == config.sourceChatId }
|
||||
) {
|
||||
startChain(
|
||||
RegistrationState.Finish(
|
||||
it.first().chat.id,
|
||||
it.map {
|
||||
PostContentInfo.fromMessage(
|
||||
it,
|
||||
0
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
startChain(RegistrationState.Finish(it.chat.id, PostContentInfo.fromMessage(it)))
|
||||
}
|
||||
koin.getOrNull<InlineTemplatesRepo>() ?.apply {
|
||||
addTemplate(
|
||||
OfferTemplate(
|
||||
"Start post",
|
||||
listOf(Format("/start_post"))
|
||||
"Start post creating",
|
||||
listOf(Format("/start_post")),
|
||||
"Use this command to start creating of complex post with several messages"
|
||||
)
|
||||
)
|
||||
addTemplate(
|
||||
OfferTemplate(
|
||||
"Finish post creating",
|
||||
listOf(Format("/finish_post")),
|
||||
"Finish creating of complex post"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
@@ -14,9 +13,5 @@ kotlin {
|
||||
api project(":plaguposter.posts")
|
||||
}
|
||||
}
|
||||
jvmMain {
|
||||
dependencies {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
@@ -15,9 +14,5 @@ kotlin {
|
||||
api libs.krontab
|
||||
}
|
||||
}
|
||||
jvmMain {
|
||||
dependencies {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
@@ -14,9 +13,5 @@ kotlin {
|
||||
api project(":plaguposter.ratings")
|
||||
}
|
||||
}
|
||||
jvmMain {
|
||||
dependencies {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
@@ -15,9 +14,5 @@ kotlin {
|
||||
api project(":plaguposter.posts.panel")
|
||||
}
|
||||
}
|
||||
jvmMain {
|
||||
dependencies {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
160
ratings/source/src/commonMain/kotlin/buttons/RootButtons.kt
Normal file
160
ratings/source/src/commonMain/kotlin/buttons/RootButtons.kt
Normal file
@@ -0,0 +1,160 @@
|
||||
package dev.inmo.plaguposter.ratings.source.buttons
|
||||
|
||||
import com.soywiz.klock.DateFormat
|
||||
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
||||
import dev.inmo.micro_utils.pagination.FirstPagePagination
|
||||
import dev.inmo.micro_utils.pagination.Pagination
|
||||
import dev.inmo.micro_utils.pagination.SimplePagination
|
||||
import dev.inmo.micro_utils.pagination.utils.paginate
|
||||
import dev.inmo.plaguposter.posts.repo.ReadPostsRepo
|
||||
import dev.inmo.plaguposter.ratings.models.Rating
|
||||
import dev.inmo.plaguposter.ratings.repo.RatingsRepo
|
||||
import dev.inmo.plaguposter.ratings.utils.postsByRatings
|
||||
import dev.inmo.tgbotapi.extensions.api.answers.answer
|
||||
import dev.inmo.tgbotapi.extensions.api.edit.edit
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onMessageDataCallbackQuery
|
||||
import dev.inmo.tgbotapi.extensions.utils.formatting.makeLinkToMessage
|
||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.dataButton
|
||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard
|
||||
import dev.inmo.tgbotapi.extensions.utils.types.buttons.urlButton
|
||||
import dev.inmo.tgbotapi.types.ChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.row
|
||||
|
||||
const val RootButtonsShowRatingData = "ratings_buttons_show"
|
||||
const val RootButtonsShowRatingPageData = "ratings_buttons_show_page"
|
||||
const val RootButtonsToPageData = "ratings_buttons_to_page"
|
||||
|
||||
suspend fun RatingsRepo.buildRootButtons(
|
||||
pagination: Pagination = FirstPagePagination(16),
|
||||
rowSize: Int = 4
|
||||
): InlineKeyboardMarkup {
|
||||
val postsByRatings = postsByRatings().toList().paginate(pagination)
|
||||
return inlineKeyboard {
|
||||
if (postsByRatings.pagesNumber > 1) {
|
||||
row {
|
||||
if (postsByRatings.page > 0) {
|
||||
dataButton("<", "$RootButtonsToPageData ${postsByRatings.page - 1} ${postsByRatings.size}")
|
||||
}
|
||||
dataButton("${postsByRatings.page}: \uD83D\uDD04", "$RootButtonsToPageData ${postsByRatings.page} ${postsByRatings.size}")
|
||||
if (postsByRatings.pagesNumber - postsByRatings.page > 1) {
|
||||
dataButton(">", "$RootButtonsToPageData ${postsByRatings.page + 1} ${postsByRatings.size}")
|
||||
}
|
||||
}
|
||||
}
|
||||
postsByRatings.results.chunked(rowSize).map {
|
||||
row {
|
||||
it.forEach { (rating, posts) ->
|
||||
dataButton("${rating.double}: ${posts.size}", "$RootButtonsShowRatingData ${rating.double}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val defaultPostCreationTimeFormat: DateFormat = DateFormat("dd.MM.yy HH:mm")
|
||||
|
||||
suspend fun RatingsRepo.buildRatingButtons(
|
||||
postsRepo: ReadPostsRepo,
|
||||
rating: Rating,
|
||||
pagination: Pagination = FirstPagePagination(8),
|
||||
rowSize: Int = 2,
|
||||
postCreationTimeFormat: DateFormat = defaultPostCreationTimeFormat
|
||||
): InlineKeyboardMarkup {
|
||||
val postsByRatings = getPosts(rating .. rating, true).keys.paginate(pagination)
|
||||
return inlineKeyboard {
|
||||
if (postsByRatings.pagesNumber > 1) {
|
||||
row {
|
||||
if (postsByRatings.page > 0) {
|
||||
dataButton("<", "$RootButtonsShowRatingPageData ${postsByRatings.page - 1} ${postsByRatings.size} ${rating.double}")
|
||||
}
|
||||
dataButton("${postsByRatings.page}: \uD83D\uDD04", "$RootButtonsShowRatingPageData ${postsByRatings.page} ${postsByRatings.size} ${rating.double}")
|
||||
if (postsByRatings.pagesNumber - postsByRatings.page > 1) {
|
||||
dataButton(">", "$RootButtonsShowRatingPageData ${postsByRatings.page + 1} ${postsByRatings.size} ${rating.double}")
|
||||
}
|
||||
}
|
||||
}
|
||||
postsByRatings.results.chunked(rowSize).map {
|
||||
row {
|
||||
it.forEach { postId ->
|
||||
val firstMessageInfo = postsRepo.getFirstMessageInfo(postId) ?: return@forEach
|
||||
val postCreationTime = postsRepo.getPostCreationTime(postId) ?: return@forEach
|
||||
urlButton(
|
||||
postCreationTime.format(postCreationTimeFormat),
|
||||
makeLinkToMessage(
|
||||
firstMessageInfo.chatId,
|
||||
firstMessageInfo.messageId
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
row {
|
||||
dataButton("↩️", "$RootButtonsToPageData 0 16")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun BehaviourContext.includeRootNavigationButtonsHandler(
|
||||
allowedChats: Set<ChatIdentifier>,
|
||||
ratingsRepo: RatingsRepo,
|
||||
postsRepo: ReadPostsRepo
|
||||
) {
|
||||
suspend fun registerPageQueryListener(
|
||||
dataPrefix: String,
|
||||
onPageUpdate: suspend (pagination: Pagination, additionalParams: Array<String>) -> InlineKeyboardMarkup?
|
||||
) {
|
||||
onMessageDataCallbackQuery(
|
||||
initialFilter = { it.message.chat.id in allowedChats }
|
||||
) {
|
||||
val args = it.data.split(" ").takeIf { it.size >= 3 } ?: return@onMessageDataCallbackQuery
|
||||
val (prefix, pageRaw, sizeRaw) = args
|
||||
|
||||
if (prefix == dataPrefix) {
|
||||
runCatchingSafely {
|
||||
val page = pageRaw.toIntOrNull() ?: return@runCatchingSafely
|
||||
val size = sizeRaw.toIntOrNull() ?: return@runCatchingSafely
|
||||
|
||||
edit(
|
||||
it.message,
|
||||
onPageUpdate(SimplePagination(page, size), args.drop(3).toTypedArray()) ?: return@runCatchingSafely
|
||||
)
|
||||
}
|
||||
|
||||
answer(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
suspend fun registerPageQueryListener(
|
||||
dataPrefix: String,
|
||||
onPageUpdate: suspend (pagination: Pagination) -> InlineKeyboardMarkup?
|
||||
) = registerPageQueryListener(dataPrefix) { pagination, _ ->
|
||||
onPageUpdate(pagination)
|
||||
}
|
||||
registerPageQueryListener(
|
||||
RootButtonsToPageData,
|
||||
ratingsRepo::buildRootButtons
|
||||
)
|
||||
registerPageQueryListener(
|
||||
RootButtonsShowRatingPageData
|
||||
) { pagination, params ->
|
||||
params.firstOrNull() ?.toDoubleOrNull() ?.let { rating ->
|
||||
ratingsRepo.buildRatingButtons(postsRepo, Rating(rating), pagination)
|
||||
}
|
||||
}
|
||||
onMessageDataCallbackQuery(
|
||||
initialFilter = { it.message.chat.id in allowedChats }
|
||||
) {
|
||||
val (prefix, ratingRaw) = it.data.split(" ").takeIf { it.size == 2 } ?: return@onMessageDataCallbackQuery
|
||||
|
||||
if (prefix == RootButtonsShowRatingData) {
|
||||
runCatchingSafely {
|
||||
val rating = ratingRaw.toDoubleOrNull() ?: return@runCatchingSafely
|
||||
edit(it.message, ratingsRepo.buildRatingButtons(postsRepo, Rating(rating)))
|
||||
}
|
||||
|
||||
answer(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,17 +11,20 @@ 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.inlines.models.Format
|
||||
import dev.inmo.plaguposter.inlines.models.OfferTemplate
|
||||
import dev.inmo.plaguposter.inlines.repos.InlineTemplatesRepo
|
||||
import dev.inmo.plagubot.plugins.inline.queries.models.Format
|
||||
import dev.inmo.plagubot.plugins.inline.queries.models.OfferTemplate
|
||||
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.plaguposter.posts.panel.PanelButtonBuilder
|
||||
import dev.inmo.plaguposter.posts.panel.PanelButtonsAPI
|
||||
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.buttons.buildRootButtons
|
||||
import dev.inmo.plaguposter.ratings.source.buttons.includeRootNavigationButtonsHandler
|
||||
import dev.inmo.plaguposter.ratings.source.models.*
|
||||
import dev.inmo.plaguposter.ratings.source.repos.*
|
||||
import dev.inmo.plaguposter.ratings.utils.postsByRatings
|
||||
import dev.inmo.tgbotapi.extensions.api.answers.answer
|
||||
import dev.inmo.tgbotapi.extensions.api.delete
|
||||
import dev.inmo.tgbotapi.extensions.api.edit.edit
|
||||
@@ -33,9 +36,12 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
|
||||
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.extensions.utils.types.buttons.inlineKeyboard
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton
|
||||
import dev.inmo.tgbotapi.types.message.textsources.bold
|
||||
import dev.inmo.tgbotapi.types.message.textsources.regular
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import dev.inmo.tgbotapi.utils.buildEntities
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.*
|
||||
@@ -79,6 +85,7 @@ object Plugin : Plugin {
|
||||
val postsRepo = koin.get<PostsRepo>()
|
||||
val config = koin.get<Config>()
|
||||
val panelApi = koin.getOrNull<PanelButtonsAPI>()
|
||||
val chatConfig = koin.get<ChatConfig>()
|
||||
|
||||
onPollUpdates (markerFactory = { it.id }) { poll ->
|
||||
val postId = pollsToPostsIdsRepo.get(poll.id) ?: return@onPollUpdates
|
||||
@@ -105,6 +112,9 @@ object Plugin : Plugin {
|
||||
pollsToPostsIdsRepo.set(sent.content.poll.id, postId)
|
||||
pollsToMessageInfoRepo.set(sent.content.poll.id, sent.short())
|
||||
}.getOrNull() ?: continue
|
||||
|
||||
delay(500L)
|
||||
|
||||
panelApi ?.forceRefresh(postId)
|
||||
return true
|
||||
}
|
||||
@@ -136,6 +146,7 @@ object Plugin : Plugin {
|
||||
|
||||
if (config.autoAttach) {
|
||||
postsRepo.newObjectsFlow.subscribeSafelyWithoutExceptions(this) {
|
||||
delay(500L)
|
||||
attachPoll(it.id)
|
||||
}
|
||||
}
|
||||
@@ -208,6 +219,32 @@ object Plugin : Plugin {
|
||||
}
|
||||
}
|
||||
}
|
||||
onCommand("ratings", requireOnlyCommandInMessage = true) {
|
||||
if (it.chat.id == chatConfig.sourceChatId) {
|
||||
val ratings = ratingsRepo.postsByRatings().toList().sortedByDescending { it.first }
|
||||
val textSources = buildEntities {
|
||||
+ "Ratings amount: " + bold("${ratings.sumOf { it.second.size }}") + "\n\n"
|
||||
ratings.forEach {
|
||||
+ "• " + bold("% 3.1f".format(it.first.double)) + ": " + bold(it.second.size.toString()) + "\n"
|
||||
}
|
||||
}
|
||||
val keyboard = flatInlineKeyboard {
|
||||
dataButton("Interactive mode", "ratings_interactive")
|
||||
}
|
||||
runCatchingSafely {
|
||||
edit(it, textSources, replyMarkup = keyboard)
|
||||
}.onFailure { _ ->
|
||||
reply(it, textSources, replyMarkup = keyboard)
|
||||
}
|
||||
}
|
||||
}
|
||||
includeRootNavigationButtonsHandler(setOf(chatConfig.sourceChatId), ratingsRepo, postsRepo)
|
||||
onMessageDataCallbackQuery("ratings_interactive", initialFilter = { it.message.chat.id == chatConfig.sourceChatId }) {
|
||||
edit(
|
||||
it.message,
|
||||
ratingsRepo.buildRootButtons()
|
||||
)
|
||||
}
|
||||
|
||||
koin.getOrNull<InlineTemplatesRepo>() ?.apply {
|
||||
addTemplate(
|
||||
|
||||
@@ -4,10 +4,12 @@ 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.IdChatIdentifier
|
||||
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
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.isNull
|
||||
import org.jetbrains.exposed.sql.statements.*
|
||||
|
||||
class ExposedPollsToMessagesInfoRepo(
|
||||
database: Database
|
||||
@@ -17,10 +19,11 @@ class ExposedPollsToMessagesInfoRepo(
|
||||
) {
|
||||
override val keyColumn = text("poll_id")
|
||||
private val chatIdColumn = long("chat_id")
|
||||
private val threadIdColumn = long("thread_id").nullable().default(null)
|
||||
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(
|
||||
override val selectById: ISqlExpressionBuilder.(PollIdentifier) -> Op<Boolean> = { keyColumn.eq(it) }
|
||||
override val selectByValue: ISqlExpressionBuilder.(ShortMessageInfo) -> Op<Boolean> = {
|
||||
chatIdColumn.eq(it.chatId.chatId).and(it.chatId.threadId ?.let { threadIdColumn.eq(it) } ?: threadIdColumn.isNull()).and(
|
||||
messageIdColumn.eq(it.messageId)
|
||||
)
|
||||
}
|
||||
@@ -28,7 +31,7 @@ class ExposedPollsToMessagesInfoRepo(
|
||||
get() = get(keyColumn)
|
||||
override val ResultRow.asObject: ShortMessageInfo
|
||||
get() = ShortMessageInfo(
|
||||
get(chatIdColumn).let(::ChatId),
|
||||
IdChatIdentifier(get(chatIdColumn), get(threadIdColumn)),
|
||||
get(messageIdColumn)
|
||||
)
|
||||
|
||||
@@ -36,14 +39,13 @@ class ExposedPollsToMessagesInfoRepo(
|
||||
initTable()
|
||||
}
|
||||
|
||||
override fun update(k: PollIdentifier, v: ShortMessageInfo, it: UpdateStatement) {
|
||||
override fun update(k: PollIdentifier, v: ShortMessageInfo, it: UpdateBuilder<Int>) {
|
||||
it[chatIdColumn] = v.chatId.chatId
|
||||
it[threadIdColumn] = v.chatId.threadId
|
||||
it[messageIdColumn] = v.messageId
|
||||
}
|
||||
|
||||
override fun insert(k: PollIdentifier, v: ShortMessageInfo, it: InsertStatement<Number>) {
|
||||
override fun insertKey(k: PollIdentifier, v: ShortMessageInfo, it: InsertStatement<Number>) {
|
||||
it[keyColumn] = k
|
||||
it[chatIdColumn] = v.chatId.chatId
|
||||
it[messageIdColumn] = v.messageId
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,16 +5,15 @@ 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
|
||||
import org.jetbrains.exposed.sql.statements.*
|
||||
|
||||
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 selectById: ISqlExpressionBuilder.(PollIdentifier) -> Op<Boolean> = { keyColumn.eq(it) }
|
||||
override val selectByValue: ISqlExpressionBuilder.(PostId) -> Op<Boolean> = { postIdColumn.eq(it.string) }
|
||||
override val ResultRow.asKey: PollIdentifier
|
||||
get() = get(keyColumn)
|
||||
override val ResultRow.asObject: PostId
|
||||
@@ -24,12 +23,11 @@ class ExposedPollsToPostsIdsRepo(
|
||||
initTable()
|
||||
}
|
||||
|
||||
override fun update(k: PollIdentifier, v: PostId, it: UpdateStatement) {
|
||||
override fun update(k: PollIdentifier, v: PostId, it: UpdateBuilder<Int>) {
|
||||
it[postIdColumn] = v.string
|
||||
}
|
||||
|
||||
override fun insert(k: PollIdentifier, v: PostId, it: InsertStatement<Number>) {
|
||||
override fun insertKey(k: PollIdentifier, v: PostId, it: InsertStatement<Number>) {
|
||||
it[keyColumn] = k
|
||||
it[postIdColumn] = v.string
|
||||
}
|
||||
}
|
||||
|
||||
15
ratings/src/commonMain/kotlin/utils/PostsByRatings.kt
Normal file
15
ratings/src/commonMain/kotlin/utils/PostsByRatings.kt
Normal file
@@ -0,0 +1,15 @@
|
||||
package dev.inmo.plaguposter.ratings.utils
|
||||
|
||||
import dev.inmo.micro_utils.pagination.utils.getAll
|
||||
import dev.inmo.micro_utils.repos.pagination.getAll
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.plaguposter.ratings.models.Rating
|
||||
import dev.inmo.plaguposter.ratings.repo.RatingsRepo
|
||||
|
||||
suspend fun RatingsRepo.postsByRatings(): Map<Rating, List<PostId>> {
|
||||
return getAll { keys(it) }.groupBy {
|
||||
it.second
|
||||
}.map {
|
||||
it.key to it.value.map { it.first }
|
||||
}.toMap()
|
||||
}
|
||||
@@ -6,8 +6,7 @@ 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.InsertStatement
|
||||
import org.jetbrains.exposed.sql.statements.UpdateStatement
|
||||
import org.jetbrains.exposed.sql.statements.*
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
|
||||
class ExposedRatingsRepo (
|
||||
@@ -18,20 +17,19 @@ class ExposedRatingsRepo (
|
||||
) {
|
||||
override val keyColumn = text("post_id")
|
||||
val ratingsColumn = double("rating")
|
||||
override val selectById: SqlExpressionBuilder.(PostId) -> Op<Boolean> = { keyColumn.eq(it.string) }
|
||||
override val selectByValue: SqlExpressionBuilder.(Rating) -> Op<Boolean> = { ratingsColumn.eq(it.double) }
|
||||
override val selectById: ISqlExpressionBuilder.(PostId) -> Op<Boolean> = { keyColumn.eq(it.string) }
|
||||
override val selectByValue: ISqlExpressionBuilder.(Rating) -> Op<Boolean> = { ratingsColumn.eq(it.double) }
|
||||
override val ResultRow.asKey: PostId
|
||||
get() = get(keyColumn).let(::PostId)
|
||||
override val ResultRow.asObject: Rating
|
||||
get() = get(ratingsColumn).let(::Rating)
|
||||
|
||||
override fun update(k: PostId, v: Rating, it: UpdateStatement) {
|
||||
override fun update(k: PostId, v: Rating, it: UpdateBuilder<Int>) {
|
||||
it[ratingsColumn] = v.double
|
||||
}
|
||||
|
||||
override fun insert(k: PostId, v: Rating, it: InsertStatement<Number>) {
|
||||
override fun insertKey(k: PostId, v: Rating, it: InsertStatement<Number>) {
|
||||
it[keyColumn] = k.string
|
||||
it[ratingsColumn] = v.double
|
||||
}
|
||||
|
||||
private fun Query.optionallyLimit(limit: Int?) = if (limit == null) {
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
},
|
||||
"botToken": "1234567890:ABCDEFGHIJKLMNOP_qrstuvwxyz12345678",
|
||||
"plugins": [
|
||||
"dev.inmo.plagubot.plugins.inline.queries.Plugin",
|
||||
"dev.inmo.plaguposter.posts.Plugin",
|
||||
"dev.inmo.plaguposter.posts.registrar.Plugin",
|
||||
"dev.inmo.plaguposter.ratings.Plugin",
|
||||
"dev.inmo.plaguposter.ratings.source.Plugin",
|
||||
"dev.inmo.plaguposter.ratings.selector.Plugin",
|
||||
"dev.inmo.plaguposter.triggers.selector_with_timer.Plugin",
|
||||
"dev.inmo.plaguposter.inlines.Plugin",
|
||||
"dev.inmo.plaguposter.triggers.command.Plugin",
|
||||
"dev.inmo.plaguposter.posts.panel.Plugin"
|
||||
],
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"dev.inmo.plaguposter.ratings.selector.Plugin",
|
||||
"dev.inmo.plaguposter.triggers.selector_with_timer.Plugin",
|
||||
"dev.inmo.plaguposter.ratings.gc.Plugin",
|
||||
"dev.inmo.plaguposter.inlines.Plugin",
|
||||
"dev.inmo.plagubot.plugins.inline.queries.Plugin",
|
||||
"dev.inmo.plaguposter.triggers.command.Plugin"
|
||||
],
|
||||
"posts": {
|
||||
|
||||
@@ -11,6 +11,7 @@ String[] includes = [
|
||||
":ratings:gc",
|
||||
":triggers:command",
|
||||
":triggers:selector_with_timer",
|
||||
":triggers:selector_with_scheduling",
|
||||
":inlines",
|
||||
// ":settings",
|
||||
":runner"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
@@ -13,9 +12,5 @@ kotlin {
|
||||
api project(":plaguposter.common")
|
||||
}
|
||||
}
|
||||
jvmMain {
|
||||
dependencies {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
@@ -16,9 +15,5 @@ kotlin {
|
||||
api project(":plaguposter.posts.panel")
|
||||
}
|
||||
}
|
||||
jvmMain {
|
||||
dependencies {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,22 @@
|
||||
package dev.inmo.plaguposter.triggers.command
|
||||
|
||||
import com.benasher44.uuid.uuid4
|
||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||
import dev.inmo.micro_utils.fsm.common.State
|
||||
import dev.inmo.micro_utils.pagination.firstPageWithOneElementPagination
|
||||
import dev.inmo.plagubot.Plugin
|
||||
import dev.inmo.plaguposter.common.SuccessfulSymbol
|
||||
import dev.inmo.plaguposter.common.UnsuccessfulSymbol
|
||||
import dev.inmo.plaguposter.inlines.models.Format
|
||||
import dev.inmo.plaguposter.inlines.models.OfferTemplate
|
||||
import dev.inmo.plaguposter.inlines.repos.InlineTemplatesRepo
|
||||
import dev.inmo.plagubot.plugins.inline.queries.models.Format
|
||||
import dev.inmo.plagubot.plugins.inline.queries.models.OfferTemplate
|
||||
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
||||
import dev.inmo.plaguposter.posts.models.PostId
|
||||
import dev.inmo.plaguposter.posts.panel.PanelButtonBuilder
|
||||
import dev.inmo.plaguposter.posts.panel.PanelButtonsAPI
|
||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||
import dev.inmo.plaguposter.posts.sending.PostPublisher
|
||||
import dev.inmo.plaguposter.ratings.selector.Selector
|
||||
import dev.inmo.tgbotapi.extensions.api.answers.answer
|
||||
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.waitMessageDataCallbackQuery
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitTextMessage
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.strictlyOn
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onMessageDataCallbackQuery
|
||||
import dev.inmo.tgbotapi.extensions.utils.*
|
||||
@@ -33,9 +26,7 @@ import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard
|
||||
import dev.inmo.tgbotapi.types.ChatId
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.message.textsources.regular
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.*
|
||||
@@ -78,7 +69,14 @@ object Plugin : Plugin {
|
||||
}
|
||||
}
|
||||
val postId = messageInReply ?.let {
|
||||
postsRepo.getIdByChatAndMessage(messageInReply.chat.id, messageInReply.messageId)
|
||||
postsRepo.getIdByChatAndMessage(messageInReply.chat.id, messageInReply.messageId) ?: let { _ ->
|
||||
reply(
|
||||
it,
|
||||
"Unable to find any post related to the message in reply"
|
||||
)
|
||||
|
||||
return@onCommand
|
||||
}
|
||||
} ?: selector ?.take(1) ?.firstOrNull()
|
||||
if (postId == null) {
|
||||
reply(
|
||||
|
||||
16
triggers/selector_with_scheduling/build.gradle
Normal file
16
triggers/selector_with_scheduling/build.gradle
Normal file
@@ -0,0 +1,16 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
|
||||
kotlin {
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
api project(":plaguposter.common")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package dev.inmo.plaguposter.triggers.selector_with_scheduling
|
||||
@@ -0,0 +1,11 @@
|
||||
package dev.inmo.plaguposter.triggers.selector_with_scheduling
|
||||
|
||||
import dev.inmo.plagubot.Plugin
|
||||
import kotlinx.serialization.json.*
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.koin.core.module.Module
|
||||
|
||||
object Plugin : Plugin {
|
||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<manifest package="dev.inmo.plaguposter.triggers.selector_with_scheduling"/>
|
||||
@@ -1,7 +1,7 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
@@ -16,9 +16,5 @@ kotlin {
|
||||
api libs.krontab
|
||||
}
|
||||
}
|
||||
jvmMain {
|
||||
dependencies {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user