diff --git a/CHANGELOG.md b/CHANGELOG.md index 16887aa..13ab6ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## 0.1.3 +* `Plugin` + * Plugin serializer + ## 0.1.2 * `Versions` 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..26b1de2 --- /dev/null +++ b/plugin/src/main/kotlin/dev/inmo/plagubot/PluginSerializer.kt @@ -0,0 +1,51 @@ +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 + ) + } + } + + override fun serialize(encoder: Encoder, value: Plugin) { + polymorphic.serialize(encoder, value) + } +} \ No newline at end of file