diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b6cc2d..4efd340 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 0.1.3 + +* `Versions` + * `tgbotapi`: `0.32.6` -> `0.32.7` +* `Bot` + * `initPlaguBot` now will return `Job` +* `Plugin` + * Plugin serializer + ## 0.1.2 * `Versions` diff --git a/bot/src/main/kotlin/dev/inmo/plagubot/App.kt b/bot/src/main/kotlin/dev/inmo/plagubot/App.kt index 5d0d004..ae68245 100644 --- a/bot/src/main/kotlin/dev/inmo/plagubot/App.kt +++ b/bot/src/main/kotlin/dev/inmo/plagubot/App.kt @@ -15,12 +15,12 @@ import java.io.File suspend inline fun initPlaguBot( config: Config, scope: CoroutineScope = CoroutineScope(Dispatchers.Default) -) { +): Job { val bot = telegramBot(config.botToken) val paramsMap = config.params ?.toMap() ?: emptyMap() val database = config.params ?.database ?: config.database.database - bot.buildBehaviour(scope) { + return bot.buildBehaviour(scope) { val commands = config.plugins.flatMap { it.apply { invoke(database, paramsMap) } it.getCommands() @@ -45,6 +45,5 @@ suspend fun main(args: Array) { val config = configSerialFormat.decodeFromString(Config.serializer(), file.readText()) val scope = CoroutineScope(Dispatchers.Default) - initPlaguBot(config, scope) - scope.coroutineContext.job.join() + initPlaguBot(config, scope).join() } diff --git a/gradle.properties b/gradle.properties index b20dd40..f7e1e74 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ kotlin_serialisation_runtime_version=1.1.0-RC kotlin_exposed_version=0.29.1 sdi_version=0.4.0-rc2 -tgbotapi_version=0.32.6 +tgbotapi_version=0.32.7 microutils_version=0.4.25 klassindex_version=4.1.0-rc.1 @@ -19,4 +19,4 @@ sqlite_version=3.30.1 github_release_plugin_version=2.2.12 group=dev.inmo -version=0.1.2 +version=0.1.3 diff --git a/plugin/src/main/kotlin/dev/inmo/plagubot/Plugin.kt b/plugin/src/main/kotlin/dev/inmo/plagubot/Plugin.kt index 74141f2..4f1ece8 100644 --- a/plugin/src/main/kotlin/dev/inmo/plagubot/Plugin.kt +++ b/plugin/src/main/kotlin/dev/inmo/plagubot/Plugin.kt @@ -5,6 +5,7 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext import dev.inmo.tgbotapi.types.BotCommand import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter import kotlinx.coroutines.CoroutineScope +import kotlinx.serialization.Serializable import org.jetbrains.exposed.sql.Database /** @@ -12,6 +13,7 @@ import org.jetbrains.exposed.sql.Database * to set up short name for your plugin. Besides, simple name of your class will be used as key for deserialization * too. */ +@Serializable(PluginSerializer::class) interface Plugin { /** * In case you want to publish some processed by your plugin commands, you can provide it via this method diff --git a/plugin/src/main/kotlin/dev/inmo/plagubot/PluginSerializer.kt b/plugin/src/main/kotlin/dev/inmo/plagubot/PluginSerializer.kt new file mode 100644 index 0000000..b21c7e7 --- /dev/null +++ b/plugin/src/main/kotlin/dev/inmo/plagubot/PluginSerializer.kt @@ -0,0 +1,53 @@ +package dev.inmo.plagubot + +import kotlinx.serialization.* +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.json.* + +private val defaultJson = Json { + ignoreUnknownKeys = true +} + +@Serializer(Plugin::class) +object PluginSerializer : KSerializer { + private val polymorphic = PolymorphicSerializer(Plugin::class) + override val descriptor: SerialDescriptor = JsonObject.serializer().descriptor + + @InternalSerializationApi + override fun deserialize(decoder: Decoder): Plugin { + val format = (decoder as? JsonDecoder) ?.json ?: defaultJson + val asJson = JsonElement.serializer().deserialize(decoder) + val jsonObject = (asJson as? JsonObject) + + val type = (jsonObject ?.get("type") as? JsonPrimitive) ?.contentOrNull + val external = if (type != null) { + try { + Class.forName(type) ?.kotlin ?.serializerOrNull() + } catch (e: Exception) { + null + } + } else { + null + } + + return if (jsonObject != null && external != null) { + format.decodeFromJsonElement( + external as KSerializer, + JsonObject(jsonObject.toMutableMap().also { it.remove("type") }) + ) + } else { + format.decodeFromJsonElement( + polymorphic, + asJson + ) + } + } + + @InternalSerializationApi + override fun serialize(encoder: Encoder, value: Plugin) { + val serializer = (value::class.serializerOrNull() ?: polymorphic) as KSerializer + serializer.serialize(encoder, value) + } +} \ No newline at end of file