package dev.inmo.tgbotapi.types.passport.encrypted import dev.inmo.micro_utils.crypto.decodeBase64 import dev.inmo.micro_utils.serialization.encapsulator.Encapsulator import dev.inmo.tgbotapi.types.hashField import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.EncryptedPassportElement import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.UnknownEncryptedPassportElement import dev.inmo.tgbotapi.types.typeField import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.nonstrictJsonFormat import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializer import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.json.* val encryptedElementsClassesByTypes = mapOf( "personal_details" to Encapsulator(EncryptedPersonalDetails::class, EncryptedPersonalDetails.serializer()), "passport" to Encapsulator(CommonPassport::class, CommonPassport.serializer()), "driver_license" to Encapsulator(DriverLicense::class, DriverLicense.serializer()), "identity_card" to Encapsulator(IdentityCard::class, IdentityCard.serializer()), "internal_passport" to Encapsulator(InternalPassport::class, InternalPassport.serializer()), "address" to Encapsulator(EncryptedAddress::class, EncryptedAddress.serializer()), "utility_bill" to Encapsulator(UtilityBill::class, UtilityBill.serializer()), "bank_statement" to Encapsulator(BankStatement::class, BankStatement.serializer()), "rental_agreement" to Encapsulator(RentalAgreement::class, RentalAgreement.serializer()), "passport_registration" to Encapsulator(PassportRegistration::class, PassportRegistration.serializer()), "temporary_registration" to Encapsulator(TemporaryRegistration::class, TemporaryRegistration.serializer()), "phone_number" to Encapsulator(PhoneNumber::class, PhoneNumber.serializer()), "email" to Encapsulator(Email::class, Email.serializer()) ) @RiskFeature("Remember that this method may return \"unknown\" in case if encrypted element was not defined in library") val EncryptedPassportElement.type: String get() = encryptedElementsClassesByTypes.keys.firstOrNull { encryptedElementsClassesByTypes.getValue(it).klass.isInstance(this) } ?: "unknown" @RiskFeature object EncryptedElementSerializer : KSerializer { private val jsonSerializer = JsonObject.serializer() override val descriptor: SerialDescriptor = jsonSerializer.descriptor override fun deserialize(decoder: Decoder): EncryptedPassportElement { val json = jsonSerializer.deserialize(decoder) return json[typeField] ?.jsonPrimitive ?.content ?.let { type -> encryptedElementsClassesByTypes[type] ?.serializer ?.let { deserializer -> nonstrictJsonFormat.decodeFromJsonElement(deserializer, json) } } ?: UnknownEncryptedPassportElement(json, json[hashField] ?.jsonPrimitive ?.content ?.decodeBase64() ?: byteArrayOf()) } override fun serialize(encoder: Encoder, value: EncryptedPassportElement) { val json = value.let { encryptedElementsClassesByTypes.forEach { (key, encapsulator) -> val json = encapsulator.encapsulate(value) { data -> nonstrictJsonFormat.encodeToJsonElement(this as KSerializer, data).jsonObject } ?: return@forEach return@let JsonObject(json + (typeField to JsonPrimitive(key))) } (value as? UnknownEncryptedPassportElement) ?.rawJson ?: return } jsonSerializer.serialize(encoder, json) } }