1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-11-27 20:48:44 +00:00

Merge branch '0.32.0' into klassindex

This commit is contained in:
InsanusMokrassar 2021-01-28 22:07:18 +06:00
commit 7cc97c12e6
64 changed files with 1025 additions and 393 deletions

16
.github/workflows/regular-build.yml vendored Normal file
View File

@ -0,0 +1,16 @@
name: Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build with Gradle
run: ./gradlew build

View File

@ -6,7 +6,9 @@
* `Common`: * `Common`:
* `Version`: * `Version`:
* `MicroUtils`: `0.4.16` -> `0.4.21` * `MicroUtils`: `0.4.16` -> `0.4.23`
* `Klock`: `0.2.3` -> `0.2.4`
* `Ktor`: `1.5.0` -> `1.5.1`
* `Core`: * `Core`:
* **BREAKING CHANGE** Now `MediaGroupMessage` have a generic type related to `MediaGroupContent` * **BREAKING CHANGE** Now `MediaGroupMessage` have a generic type related to `MediaGroupContent`
* Methods and types related to `MediaGroupMessage` have been modified according to their meanings * Methods and types related to `MediaGroupMessage` have been modified according to their meanings
@ -19,6 +21,8 @@
* `onVisualMediaGroup` now is just an alternative to `onVisualGallery` * `onVisualMediaGroup` now is just an alternative to `onVisualGallery`
* `command` and `onCommand` expectations has been added for commands `String` variant * `command` and `onCommand` expectations has been added for commands `String` variant
* New extensions `BehaviourContext#oneOf`, `BehaviourContext#parallel` and `Deferred<T>#withAction` * New extensions `BehaviourContext#oneOf`, `BehaviourContext#parallel` and `Deferred<T>#withAction`
* `API`:
* **PASSPORT** New extensions `TelegramBot#setPassportDataErrors`
## 0.31.0 ## 0.31.0

View File

@ -8,11 +8,11 @@ kotlin.incremental.js=true
kotlin_version=1.4.21 kotlin_version=1.4.21
kotlin_coroutines_version=1.4.2 kotlin_coroutines_version=1.4.2
kotlin_serialisation_runtime_version=1.0.1 kotlin_serialisation_runtime_version=1.0.1
klock_version=2.0.3 klock_version=2.0.4
uuid_version=0.2.3 uuid_version=0.2.3
ktor_version=1.5.0 ktor_version=1.5.1
micro_utils_version=0.4.21 micro_utils_version=0.4.23
javax_activation_version=1.1.1 javax_activation_version=1.1.1

View File

@ -379,3 +379,17 @@ const val fileHashField = "file_hash"
const val fileHashesField = "file_hashes" const val fileHashesField = "file_hashes"
const val messageField = "message" const val messageField = "message"
const val unspecifiedField = "unspecified" const val unspecifiedField = "unspecified"
const val secureDataField = "secure_data"
const val nonceField = "nonce"
const val personalDetailsField = "personal_details"
const val passportField = "passport"
const val internalPassportField = "internal_passport"
const val driverLicenseField = "driver_license"
const val identityCardField = "identity_card"
const val utilityBillField = "utility_bill"
const val bankStatementField = "bank_statement"
const val rentalAgreementField = "rental_agreement"
const val passportRegistrationField = "passport_registration"
const val temporaryRegistrationField = "temporary_registration"

View File

@ -1,23 +0,0 @@
package dev.inmo.tgbotapi.types.passport
import dev.inmo.micro_utils.serialization.base64.Base64StringSerializer
import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
typealias EncryptedAndBase64EncodedData = String
typealias EncryptedByBotPublicKeyData = String
typealias EncryptedData = String
@Serializable
data class EncryptedCredentials(
@SerialName(dataField)
@Serializable(Base64StringSerializer::class)
val data: EncryptedData,
@SerialName(hashField)
@Serializable(Base64StringSerializer::class)
val hash: String,
@SerialName(secretField)
@Serializable(Base64StringSerializer::class)
val secret: EncryptedByBotPublicKeyData
)

View File

@ -2,7 +2,8 @@ package dev.inmo.tgbotapi.types.passport
import dev.inmo.tgbotapi.types.credentialsField import dev.inmo.tgbotapi.types.credentialsField
import dev.inmo.tgbotapi.types.dataField import dev.inmo.tgbotapi.types.dataField
import dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts.EncryptedPassportElement import dev.inmo.tgbotapi.types.passport.credentials.EncryptedCredentials
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.EncryptedPassportElement
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -4,10 +4,10 @@ package dev.inmo.tgbotapi.types.passport
import dev.inmo.micro_utils.crypto.MD5 import dev.inmo.micro_utils.crypto.MD5
import dev.inmo.micro_utils.crypto.md5 import dev.inmo.micro_utils.crypto.md5
import dev.inmo.micro_utils.serialization.base64.Base64StringSerializer import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts.* import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.*
import dev.inmo.tgbotapi.types.passport.encrypted_data.type import dev.inmo.tgbotapi.types.passport.encrypted.type
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor
@ -70,12 +70,12 @@ object PassportElementErrorSerializer : KSerializer<PassportElementError> {
@Serializable @Serializable
sealed class PassportSingleElementError : PassportElementError() { sealed class PassportSingleElementError : PassportElementError() {
abstract val elementHash: String abstract val elementHash: PassportElementHash
} }
@Serializable @Serializable
sealed class PassportMultipleElementsError : PassportElementError() { sealed class PassportMultipleElementsError : PassportElementError() {
abstract val elementsHashes: List<String> abstract val elementsHashes: List<PassportElementHash>
} }
@Serializable @Serializable
@ -91,8 +91,8 @@ data class PassportElementErrorDataField(
@SerialName(fieldNameField) @SerialName(fieldNameField)
val fieldName: String, val fieldName: String,
@SerialName(dataHashField) @SerialName(dataHashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val elementHash: String, override val elementHash: PassportElementHash,
@SerialName(messageField) @SerialName(messageField)
override val message: String override val message: String
) : PassportSingleElementError() { ) : PassportSingleElementError() {
@ -112,8 +112,8 @@ data class PassportElementErrorFrontSide(
@SerialName(typeField) @SerialName(typeField)
override val type: String, override val type: String,
@SerialName(fileHashField) @SerialName(fileHashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val elementHash: String, override val elementHash: PassportElementHash,
@SerialName(messageField) @SerialName(messageField)
override val message: String override val message: String
) : PassportElementFileError() { ) : PassportElementFileError() {
@ -121,7 +121,7 @@ data class PassportElementErrorFrontSide(
@Required @Required
override val source: String = frontSideField override val source: String = frontSideField
} }
fun WithFrontSide.createFrontSideError(message: String, unencryptedFileHash: String) = PassportElementErrorFrontSide( fun WithFrontSide.createFrontSideError(message: String, unencryptedFileHash: PassportElementHash) = PassportElementErrorFrontSide(
type, type,
unencryptedFileHash, unencryptedFileHash,
message message
@ -132,8 +132,8 @@ data class PassportElementErrorReverseSide(
@SerialName(typeField) @SerialName(typeField)
override val type: String, override val type: String,
@SerialName(fileHashField) @SerialName(fileHashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val elementHash: String, override val elementHash: PassportElementHash,
@SerialName(messageField) @SerialName(messageField)
override val message: String override val message: String
) : PassportElementFileError() { ) : PassportElementFileError() {
@ -141,7 +141,7 @@ data class PassportElementErrorReverseSide(
@Required @Required
override val source: String = reverseSideField override val source: String = reverseSideField
} }
fun WithReverseSide.createReverseSideError(message: String, unencryptedFileHash: String) = PassportElementErrorReverseSide( fun WithReverseSide.createReverseSideError(message: String, unencryptedFileHash: PassportElementHash) = PassportElementErrorReverseSide(
type, type,
unencryptedFileHash, unencryptedFileHash,
message message
@ -151,8 +151,8 @@ data class PassportElementErrorSelfie(
@SerialName(typeField) @SerialName(typeField)
override val type: String, override val type: String,
@SerialName(fileHashField) @SerialName(fileHashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val elementHash: String, override val elementHash: PassportElementHash,
@SerialName(messageField) @SerialName(messageField)
override val message: String override val message: String
) : PassportElementFileError() { ) : PassportElementFileError() {
@ -160,7 +160,7 @@ data class PassportElementErrorSelfie(
@Required @Required
override val source: String = selfieField override val source: String = selfieField
} }
fun WithSelfie.createSelfieError(message: String, unencryptedFileHash: String) = PassportElementErrorSelfie( fun WithSelfie.createSelfieError(message: String, unencryptedFileHash: PassportElementHash) = PassportElementErrorSelfie(
type, type,
unencryptedFileHash, unencryptedFileHash,
message message
@ -172,8 +172,8 @@ data class PassportElementErrorFile(
@SerialName(typeField) @SerialName(typeField)
override val type: String, override val type: String,
@SerialName(fileHashField) @SerialName(fileHashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val elementHash: String, override val elementHash: PassportElementHash,
@SerialName(messageField) @SerialName(messageField)
override val message: String override val message: String
) : PassportElementFileError() { ) : PassportElementFileError() {
@ -181,7 +181,7 @@ data class PassportElementErrorFile(
@Required @Required
override val source: String = fileField override val source: String = fileField
} }
fun FilesCollection.createFileError(message: String, unencryptedFileHash: String) = PassportElementErrorFile( fun FilesCollection.createFileError(message: String, unencryptedFileHash: PassportElementHash) = PassportElementErrorFile(
type, type,
unencryptedFileHash, unencryptedFileHash,
message message
@ -192,7 +192,7 @@ data class PassportElementErrorFiles(
@SerialName(typeField) @SerialName(typeField)
override val type: String, override val type: String,
@SerialName(fileHashesField) @SerialName(fileHashesField)
override val elementsHashes: List<@Serializable(Base64StringSerializer::class) String>, override val elementsHashes: List<@Serializable(Base64BytesToFromStringSerializer::class) PassportElementHash>,
@SerialName(messageField) @SerialName(messageField)
override val message: String override val message: String
) : PassportElementFilesError() { ) : PassportElementFilesError() {
@ -200,7 +200,7 @@ data class PassportElementErrorFiles(
@Required @Required
override val source: String = filesField override val source: String = filesField
} }
fun FilesCollection.createFilesError(message: String, unencryptedFileHashes: List<String>) = PassportElementErrorFiles( fun FilesCollection.createFilesError(message: String, unencryptedFileHashes: List<PassportElementHash>) = PassportElementErrorFiles(
type, type,
unencryptedFileHashes, unencryptedFileHashes,
message message
@ -212,8 +212,8 @@ data class PassportElementErrorTranslationFile(
@SerialName(typeField) @SerialName(typeField)
override val type: String, override val type: String,
@SerialName(fileHashField) @SerialName(fileHashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val elementHash: String, override val elementHash: PassportElementHash,
@SerialName(messageField) @SerialName(messageField)
override val message: String override val message: String
) : PassportElementFileError() { ) : PassportElementFileError() {
@ -221,7 +221,7 @@ data class PassportElementErrorTranslationFile(
@Required @Required
override val source: String = translationFileField override val source: String = translationFileField
} }
fun Translatable.createFileError(message: String, unencryptedFileHash: String) = PassportElementErrorTranslationFile( fun Translatable.createFileError(message: String, unencryptedFileHash: PassportElementHash) = PassportElementErrorTranslationFile(
type, type,
unencryptedFileHash, unencryptedFileHash,
message message
@ -231,7 +231,7 @@ data class PassportElementErrorTranslationFiles(
@SerialName(typeField) @SerialName(typeField)
override val type: String, override val type: String,
@SerialName(fileHashesField) @SerialName(fileHashesField)
override val elementsHashes: List<@Serializable(Base64StringSerializer::class) String>, override val elementsHashes: List<@Serializable(Base64BytesToFromStringSerializer::class) PassportElementHash>,
@SerialName(messageField) @SerialName(messageField)
override val message: String override val message: String
) : PassportElementFilesError() { ) : PassportElementFilesError() {
@ -239,7 +239,7 @@ data class PassportElementErrorTranslationFiles(
@Required @Required
override val source: String = translationFilesField override val source: String = translationFilesField
} }
fun Translatable.createFilesError(message: String, unencryptedFileHashes: List<String>) = PassportElementErrorTranslationFiles( fun Translatable.createFilesError(message: String, unencryptedFileHashes: List<PassportElementHash>) = PassportElementErrorTranslationFiles(
type, type,
unencryptedFileHashes, unencryptedFileHashes,
message message
@ -250,8 +250,8 @@ data class PassportElementErrorUnspecified(
@SerialName(typeField) @SerialName(typeField)
override val type: String, override val type: String,
@SerialName(fileHashField) @SerialName(fileHashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val elementHash: String, override val elementHash: PassportElementHash,
@SerialName(messageField) @SerialName(messageField)
override val message: String override val message: String
) : PassportElementFileError() { ) : PassportElementFileError() {
@ -259,7 +259,7 @@ data class PassportElementErrorUnspecified(
@Required @Required
override val source: String = unspecifiedField override val source: String = unspecifiedField
} }
fun EncryptedPassportElement.createUnspecifiedError(message: String, elementHash: String) = PassportElementErrorUnspecified( fun EncryptedPassportElement.createUnspecifiedError(message: String, elementHash: PassportElementHash) = PassportElementErrorUnspecified(
type, type,
elementHash, elementHash,
message message

View File

@ -0,0 +1,15 @@
package dev.inmo.tgbotapi.types.passport.credentials
import dev.inmo.tgbotapi.types.nonceField
import dev.inmo.tgbotapi.types.passport.decrypted.SecureData
import dev.inmo.tgbotapi.types.secureDataField
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class DecryptedCredentials(
@SerialName(secureDataField)
val secureData: SecureData,
@SerialName(nonceField)
val nonce: String
)

View File

@ -0,0 +1,23 @@
package dev.inmo.tgbotapi.types.passport.credentials
import dev.inmo.micro_utils.crypto.SourceBytes
import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
typealias EncryptedByBotPublicKeyData = SourceBytes
typealias EncryptedData = SourceBytes
@Serializable
data class EncryptedCredentials(
@SerialName(dataField)
@Serializable(Base64BytesToFromStringSerializer::class)
val data: EncryptedData,
@SerialName(hashField)
@Serializable(Base64BytesToFromStringSerializer::class)
val hash: SourceBytes,
@SerialName(secretField)
@Serializable(Base64BytesToFromStringSerializer::class)
val secret: EncryptedByBotPublicKeyData
)

View File

@ -0,0 +1,35 @@
package dev.inmo.tgbotapi.types.passport.credentials
import dev.inmo.micro_utils.crypto.SourceBytes
import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
sealed class EndDataCredentials {
@Serializable(Base64BytesToFromStringSerializer::class)
abstract val hash: SourceBytes
@Serializable(Base64BytesToFromStringSerializer::class)
abstract val secret: SourceBytes
}
@Serializable
data class DataCredentials(
@SerialName(dataHashField)
@Serializable(Base64BytesToFromStringSerializer::class)
override val hash: SourceBytes,
@SerialName(secretField)
@Serializable(Base64BytesToFromStringSerializer::class)
override val secret: SourceBytes
) : EndDataCredentials()
@Serializable
data class FileCredentials(
@SerialName(fileHashField)
@Serializable(Base64BytesToFromStringSerializer::class)
override val hash: SourceBytes,
@SerialName(secretField)
@Serializable(Base64BytesToFromStringSerializer::class)
override val secret: SourceBytes
) : EndDataCredentials()

View File

@ -0,0 +1,16 @@
package dev.inmo.tgbotapi.types.passport.decrypted
import dev.inmo.tgbotapi.types.dataField
import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials
import dev.inmo.tgbotapi.types.passport.credentials.EndDataCredentials
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithData
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class AddressSecureValue(
@SerialName(dataField)
override val data: DataCredentials
) : SecureValueWithData {
override val credentials: List<EndDataCredentials> = listOf(data)
}

View File

@ -0,0 +1,41 @@
package dev.inmo.tgbotapi.types.passport.decrypted
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.passport.credentials.*
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
sealed class IdentityWithReverseSideSecureValue : SecureValueIdentity, SecureValueWithData, SecureValueWithTranslations, SecureValueWithReverseSide {
override val credentials: List<EndDataCredentials>
get() = listOfNotNull(data, frontSide, reverseSide, selfie) + translation
}
@Serializable
data class DriverLicenseSecureValue(
@SerialName(dataField)
override val data: DataCredentials? = null,
@SerialName(frontSideField)
override val frontSide: FileCredentials? = null,
@SerialName(reverseSideField)
override val reverseSide: FileCredentials? = null,
@SerialName(selfieField)
override val selfie: FileCredentials? = null,
@SerialName(translationField)
override val translation: List<FileCredentials> = emptyList()
) : IdentityWithReverseSideSecureValue()
@Serializable
data class IdentityCardSecureValue(
@SerialName(dataField)
override val data: DataCredentials? = null,
@SerialName(frontSideField)
override val frontSide: FileCredentials? = null,
@SerialName(reverseSideField)
override val reverseSide: FileCredentials? = null,
@SerialName(selfieField)
override val selfie: FileCredentials? = null,
@SerialName(translationField)
override val translation: List<FileCredentials> = emptyList()
) : IdentityWithReverseSideSecureValue()

View File

@ -0,0 +1,56 @@
package dev.inmo.tgbotapi.types.passport.decrypted
import dev.inmo.tgbotapi.types.filesField
import dev.inmo.tgbotapi.types.passport.credentials.EndDataCredentials
import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithFiles
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithTranslations
import dev.inmo.tgbotapi.types.translationField
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
sealed class OtherDocumentsSecureValue : SecureValueWithTranslations, SecureValueWithFiles {
override val credentials: List<EndDataCredentials>
get() = translation + files
}
@Serializable
data class UtilityBillSecureValue(
@SerialName(translationField)
override val translation: List<FileCredentials> = emptyList(),
@SerialName(filesField)
override val files: List<FileCredentials> = emptyList()
) : OtherDocumentsSecureValue()
@Serializable
data class BankStatementSecureValue(
@SerialName(translationField)
override val translation: List<FileCredentials> = emptyList(),
@SerialName(filesField)
override val files: List<FileCredentials> = emptyList()
) : OtherDocumentsSecureValue()
@Serializable
data class RentalAgreementSecureValue(
@SerialName(translationField)
override val translation: List<FileCredentials> = emptyList(),
@SerialName(filesField)
override val files: List<FileCredentials> = emptyList()
) : OtherDocumentsSecureValue()
@Serializable
data class PassportRegistrationSecureValue(
@SerialName(translationField)
override val translation: List<FileCredentials> = emptyList(),
@SerialName(filesField)
override val files: List<FileCredentials> = emptyList()
) : OtherDocumentsSecureValue()
@Serializable
data class TemporalRegistrationSecureValue(
@SerialName(translationField)
override val translation: List<FileCredentials> = emptyList(),
@SerialName(filesField)
override val files: List<FileCredentials> = emptyList()
) : OtherDocumentsSecureValue()

View File

@ -0,0 +1,38 @@
package dev.inmo.tgbotapi.types.passport.decrypted
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.passport.credentials.*
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
sealed class PassportSecureValue : SecureValueIdentity, SecureValueWithData, SecureValueWithTranslations {
override val credentials: List<EndDataCredentials>
get() = listOfNotNull(data, frontSide, selfie) + translation
}
@Serializable
data class CommonPassportSecureValue(
@SerialName(dataField)
override val data: DataCredentials? = null,
@SerialName(frontSideField)
override val frontSide: FileCredentials? = null,
@SerialName(selfieField)
override val selfie: FileCredentials? = null,
@SerialName(translationField)
override val translation: List<FileCredentials> = emptyList()
) : PassportSecureValue()
@Serializable
data class InternalPassportSecureValue(
@SerialName(dataField)
override val data: DataCredentials? = null,
@SerialName(frontSideField)
override val frontSide: FileCredentials? = null,
@SerialName(selfieField)
override val selfie: FileCredentials? = null,
@SerialName(translationField)
override val translation: List<FileCredentials> = emptyList()
) : PassportSecureValue()

View File

@ -0,0 +1,16 @@
package dev.inmo.tgbotapi.types.passport.decrypted
import dev.inmo.tgbotapi.types.dataField
import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials
import dev.inmo.tgbotapi.types.passport.credentials.EndDataCredentials
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithData
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class PersonalDetailsSecureValue(
@SerialName(dataField)
override val data: DataCredentials
) : SecureValueWithData {
override val credentials: List<EndDataCredentials> = listOf(data)
}

View File

@ -0,0 +1,42 @@
package dev.inmo.tgbotapi.types.passport.decrypted
import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class SecureData(
@SerialName(personalDetailsField)
val personalDetails: PersonalDetailsSecureValue? = null,
@SerialName(passportField)
val passport: CommonPassportSecureValue? = null,
@SerialName(internalPassportField)
val internalPassport: InternalPassportSecureValue? = null,
@SerialName(driverLicenseField)
val driverLicense: DriverLicenseSecureValue? = null,
@SerialName(identityCardField)
val identityCard: IdentityCardSecureValue? = null,
@SerialName(utilityBillField)
val utilityBill: UtilityBillSecureValue? = null,
@SerialName(bankStatementField)
val bankStatement: BankStatementSecureValue? = null,
@SerialName(rentalAgreementField)
val rentalAgreement: RentalAgreementSecureValue? = null,
@SerialName(passportRegistrationField)
val passportRegistration: PassportRegistrationSecureValue? = null,
@SerialName(temporaryRegistrationField)
val temporaryRegistration: TemporalRegistrationSecureValue? = null,
) {
val allCredentials by lazy {
(personalDetails ?.credentials ?: emptyList()) +
(passport ?.credentials ?: emptyList()) +
(internalPassport ?.credentials ?: emptyList()) +
(driverLicense ?.credentials ?: emptyList()) +
(identityCard ?.credentials ?: emptyList()) +
(utilityBill ?.credentials ?: emptyList()) +
(bankStatement ?.credentials ?: emptyList()) +
(rentalAgreement ?.credentials ?: emptyList()) +
(passportRegistration ?.credentials ?: emptyList()) +
(temporaryRegistration ?.credentials ?: emptyList())
}
}

View File

@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.types.passport.decrypted.abstracts
import dev.inmo.tgbotapi.types.passport.credentials.EndDataCredentials
interface SecureValue {
val credentials: List<EndDataCredentials>
}

View File

@ -0,0 +1,8 @@
package dev.inmo.tgbotapi.types.passport.decrypted.abstracts
import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials
interface SecureValueIdentity : SecureValue {
val frontSide: FileCredentials?
val selfie: FileCredentials?
}

View File

@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.types.passport.decrypted.abstracts
import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials
interface SecureValueWithData : SecureValue {
val data: DataCredentials?
}

View File

@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.types.passport.decrypted.abstracts
import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials
interface SecureValueWithFiles : SecureValue {
val files: List<FileCredentials>
}

View File

@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.types.passport.decrypted.abstracts
import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials
interface SecureValueWithReverseSide : SecureValue {
val reverseSide: FileCredentials?
}

View File

@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.types.passport.decrypted.abstracts
import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials
interface SecureValueWithTranslations : SecureValue {
val translation: List<FileCredentials>
}

View File

@ -0,0 +1,19 @@
package dev.inmo.tgbotapi.types.passport.encrypted
import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
import dev.inmo.tgbotapi.types.emailField
import dev.inmo.tgbotapi.types.hashField
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.PassportElementHash
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.WithEmail
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class Email(
@SerialName(emailField)
override val email: String,
@SerialName(hashField)
@Serializable(Base64BytesToFromStringSerializer::class)
override val hash: PassportElementHash
) : WithEmail {
}

View File

@ -0,0 +1,18 @@
package dev.inmo.tgbotapi.types.passport.encrypted
import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
import dev.inmo.tgbotapi.types.dataField
import dev.inmo.tgbotapi.types.passport.credentials.EncryptedData
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.PassportElementHash
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.WithData
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class EncryptedAddress(
@SerialName(dataField)
@Serializable(Base64BytesToFromStringSerializer::class)
override val data: EncryptedData,
@Serializable(Base64BytesToFromStringSerializer::class)
override val hash: PassportElementHash
) : WithData

View File

@ -1,9 +1,10 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data 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.micro_utils.serialization.encapsulator.Encapsulator
import dev.inmo.tgbotapi.types.hashField import dev.inmo.tgbotapi.types.hashField
import dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts.EncryptedPassportElement import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.EncryptedPassportElement
import dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts.UnknownEncryptedPassportElement import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.UnknownEncryptedPassportElement
import dev.inmo.tgbotapi.types.typeField import dev.inmo.tgbotapi.types.typeField
import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
@ -45,7 +46,7 @@ object EncryptedElementSerializer : KSerializer<EncryptedPassportElement> {
encryptedElementsClassesByTypes[type] ?.serializer ?.let { deserializer -> encryptedElementsClassesByTypes[type] ?.serializer ?.let { deserializer ->
nonstrictJsonFormat.decodeFromJsonElement(deserializer, json) nonstrictJsonFormat.decodeFromJsonElement(deserializer, json)
} }
} ?: UnknownEncryptedPassportElement(json, json[hashField] ?.jsonPrimitive ?.content ?: "") } ?: UnknownEncryptedPassportElement(json, json[hashField] ?.jsonPrimitive ?.content ?.decodeBase64() ?: byteArrayOf())
} }
override fun serialize(encoder: Encoder, value: EncryptedPassportElement) { override fun serialize(encoder: Encoder, value: EncryptedPassportElement) {

View File

@ -0,0 +1,18 @@
package dev.inmo.tgbotapi.types.passport.encrypted
import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
import dev.inmo.tgbotapi.types.dataField
import dev.inmo.tgbotapi.types.passport.credentials.EncryptedData
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.PassportElementHash
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.WithData
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class EncryptedPersonalDetails(
@SerialName(dataField)
@Serializable(Base64BytesToFromStringSerializer::class)
override val data: EncryptedData,
@Serializable(Base64BytesToFromStringSerializer::class)
override val hash: PassportElementHash
) : WithData

View File

@ -1,9 +1,9 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data package dev.inmo.tgbotapi.types.passport.encrypted
import dev.inmo.micro_utils.serialization.base64.Base64StringSerializer import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.passport.EncryptedData import dev.inmo.tgbotapi.types.passport.credentials.EncryptedData
import dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts.* import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.*
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -13,7 +13,7 @@ sealed class Passport : WithData, WithFrontSide, WithSelfie, Translatable
@Serializable @Serializable
data class CommonPassport( data class CommonPassport(
@SerialName(dataField) @SerialName(dataField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val data: EncryptedData, override val data: EncryptedData,
@SerialName(frontSideField) @SerialName(frontSideField)
override val frontSide: PassportFile? = null, override val frontSide: PassportFile? = null,
@ -22,13 +22,13 @@ data class CommonPassport(
@SerialName(translationField) @SerialName(translationField)
override val translations: List<PassportFile> = emptyList(), override val translations: List<PassportFile> = emptyList(),
@SerialName(hashField) @SerialName(hashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val hash: String override val hash: PassportElementHash
) : Passport() ) : Passport()
@Serializable @Serializable
data class InternalPassport( data class InternalPassport(
@SerialName(dataField) @SerialName(dataField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val data: EncryptedData, override val data: EncryptedData,
@SerialName(frontSideField) @SerialName(frontSideField)
override val frontSide: PassportFile? = null, override val frontSide: PassportFile? = null,
@ -37,6 +37,6 @@ data class InternalPassport(
@SerialName(translationField) @SerialName(translationField)
override val translations: List<PassportFile> = emptyList(), override val translations: List<PassportFile> = emptyList(),
@SerialName(hashField) @SerialName(hashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val hash: String override val hash: PassportElementHash
) : Passport() ) : Passport()

View File

@ -1,4 +1,4 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data package dev.inmo.tgbotapi.types.passport.encrypted
import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*

View File

@ -0,0 +1,19 @@
package dev.inmo.tgbotapi.types.passport.encrypted
import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
import dev.inmo.tgbotapi.types.hashField
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.PassportElementHash
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.WithPhoneNumber
import dev.inmo.tgbotapi.types.phoneNumberField
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class PhoneNumber(
@SerialName(phoneNumberField)
override val phoneNumber: String,
@SerialName(hashField)
@Serializable(Base64BytesToFromStringSerializer::class)
override val hash: PassportElementHash
) : WithPhoneNumber {
}

View File

@ -1,9 +1,8 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data package dev.inmo.tgbotapi.types.passport.encrypted
import dev.inmo.micro_utils.serialization.base64.Base64StringSerializer import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts.FilesCollection import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.*
import dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts.Translatable
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -17,8 +16,8 @@ data class UtilityBill(
@SerialName(translationField) @SerialName(translationField)
override val translations: List<PassportFile> = emptyList(), override val translations: List<PassportFile> = emptyList(),
@SerialName(hashField) @SerialName(hashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val hash: String override val hash: PassportElementHash
) : TranslatableFilesCollection() ) : TranslatableFilesCollection()
@Serializable @Serializable
data class BankStatement( data class BankStatement(
@ -27,8 +26,8 @@ data class BankStatement(
@SerialName(translationField) @SerialName(translationField)
override val translations: List<PassportFile> = emptyList(), override val translations: List<PassportFile> = emptyList(),
@SerialName(hashField) @SerialName(hashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val hash: String override val hash: PassportElementHash
) : TranslatableFilesCollection() ) : TranslatableFilesCollection()
@Serializable @Serializable
data class RentalAgreement( data class RentalAgreement(
@ -37,8 +36,8 @@ data class RentalAgreement(
@SerialName(translationField) @SerialName(translationField)
override val translations: List<PassportFile> = emptyList(), override val translations: List<PassportFile> = emptyList(),
@SerialName(hashField) @SerialName(hashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val hash: String override val hash: PassportElementHash
) : TranslatableFilesCollection() ) : TranslatableFilesCollection()
@Serializable @Serializable
data class PassportRegistration( data class PassportRegistration(
@ -47,8 +46,8 @@ data class PassportRegistration(
@SerialName(translationField) @SerialName(translationField)
override val translations: List<PassportFile> = emptyList(), override val translations: List<PassportFile> = emptyList(),
@SerialName(hashField) @SerialName(hashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val hash: String override val hash: PassportElementHash
) : TranslatableFilesCollection() ) : TranslatableFilesCollection()
@Serializable @Serializable
data class TemporaryRegistration( data class TemporaryRegistration(
@ -57,7 +56,7 @@ data class TemporaryRegistration(
@SerialName(translationField) @SerialName(translationField)
override val translations: List<PassportFile> = emptyList(), override val translations: List<PassportFile> = emptyList(),
@SerialName(hashField) @SerialName(hashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val hash: String override val hash: PassportElementHash
) : TranslatableFilesCollection() ) : TranslatableFilesCollection()

View File

@ -1,9 +1,9 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data package dev.inmo.tgbotapi.types.passport.encrypted
import dev.inmo.micro_utils.serialization.base64.Base64StringSerializer import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.passport.EncryptedData import dev.inmo.tgbotapi.types.passport.credentials.EncryptedData
import dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts.* import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.*
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -13,7 +13,7 @@ sealed class TranslatableIDDocument : WithData, WithFrontSide, WithReverseSide,
@Serializable @Serializable
data class DriverLicense( data class DriverLicense(
@SerialName(dataField) @SerialName(dataField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val data: EncryptedData, override val data: EncryptedData,
@SerialName(frontSideField) @SerialName(frontSideField)
override val frontSide: PassportFile? = null, override val frontSide: PassportFile? = null,
@ -24,14 +24,14 @@ data class DriverLicense(
@SerialName(translationField) @SerialName(translationField)
override val translations: List<PassportFile> = emptyList(), override val translations: List<PassportFile> = emptyList(),
@SerialName(hashField) @SerialName(hashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val hash: String override val hash: PassportElementHash
) : TranslatableIDDocument() ) : TranslatableIDDocument()
@Serializable @Serializable
data class IdentityCard( data class IdentityCard(
@SerialName(dataField) @SerialName(dataField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val data: EncryptedData, override val data: EncryptedData,
@SerialName(frontSideField) @SerialName(frontSideField)
override val frontSide: PassportFile? = null, override val frontSide: PassportFile? = null,
@ -42,6 +42,6 @@ data class IdentityCard(
@SerialName(translationField) @SerialName(translationField)
override val translations: List<PassportFile> = emptyList(), override val translations: List<PassportFile> = emptyList(),
@SerialName(hashField) @SerialName(hashField)
@Serializable(Base64StringSerializer::class) @Serializable(Base64BytesToFromStringSerializer::class)
override val hash: String override val hash: PassportElementHash
) : TranslatableIDDocument() ) : TranslatableIDDocument()

View File

@ -0,0 +1,21 @@
package dev.inmo.tgbotapi.types.passport.encrypted.abstracts
import dev.inmo.micro_utils.crypto.SourceBytes
import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
import dev.inmo.tgbotapi.types.passport.encrypted.EncryptedElementSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject
typealias PassportElementHash = SourceBytes
@Serializable(EncryptedElementSerializer::class)
interface EncryptedPassportElement {
val hash: PassportElementHash
}
@Serializable(EncryptedElementSerializer::class)
data class UnknownEncryptedPassportElement(
val rawJson: JsonObject,
@Serializable(Base64BytesToFromStringSerializer::class)
override val hash: PassportElementHash
) : EncryptedPassportElement

View File

@ -0,0 +1,10 @@
package dev.inmo.tgbotapi.types.passport.encrypted.abstracts
import dev.inmo.tgbotapi.types.passport.encrypted.EncryptedElementSerializer
import dev.inmo.tgbotapi.types.passport.encrypted.PassportFile
import kotlinx.serialization.Serializable
@Serializable(EncryptedElementSerializer::class)
interface FilesCollection : EncryptedPassportElement {
val files: List<PassportFile>
}

View File

@ -0,0 +1,10 @@
package dev.inmo.tgbotapi.types.passport.encrypted.abstracts
import dev.inmo.tgbotapi.types.passport.encrypted.EncryptedElementSerializer
import dev.inmo.tgbotapi.types.passport.encrypted.PassportFile
import kotlinx.serialization.Serializable
@Serializable(EncryptedElementSerializer::class)
interface Translatable : EncryptedPassportElement {
val translations: List<PassportFile>
}

View File

@ -0,0 +1,10 @@
package dev.inmo.tgbotapi.types.passport.encrypted.abstracts
import dev.inmo.tgbotapi.types.passport.credentials.EncryptedData
import dev.inmo.tgbotapi.types.passport.encrypted.EncryptedElementSerializer
import kotlinx.serialization.Serializable
@Serializable(EncryptedElementSerializer::class)
interface WithData : EncryptedPassportElement {
val data: EncryptedData
}

View File

@ -1,6 +1,6 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts package dev.inmo.tgbotapi.types.passport.encrypted.abstracts
import dev.inmo.tgbotapi.types.passport.encrypted_data.EncryptedElementSerializer import dev.inmo.tgbotapi.types.passport.encrypted.EncryptedElementSerializer
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable(EncryptedElementSerializer::class) @Serializable(EncryptedElementSerializer::class)

View File

@ -0,0 +1,10 @@
package dev.inmo.tgbotapi.types.passport.encrypted.abstracts
import dev.inmo.tgbotapi.types.passport.encrypted.EncryptedElementSerializer
import dev.inmo.tgbotapi.types.passport.encrypted.PassportFile
import kotlinx.serialization.Serializable
@Serializable(EncryptedElementSerializer::class)
interface WithFrontSide : EncryptedPassportElement {
val frontSide: PassportFile?
}

View File

@ -1,6 +1,6 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts package dev.inmo.tgbotapi.types.passport.encrypted.abstracts
import dev.inmo.tgbotapi.types.passport.encrypted_data.EncryptedElementSerializer import dev.inmo.tgbotapi.types.passport.encrypted.EncryptedElementSerializer
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable(EncryptedElementSerializer::class) @Serializable(EncryptedElementSerializer::class)

View File

@ -0,0 +1,10 @@
package dev.inmo.tgbotapi.types.passport.encrypted.abstracts
import dev.inmo.tgbotapi.types.passport.encrypted.EncryptedElementSerializer
import dev.inmo.tgbotapi.types.passport.encrypted.PassportFile
import kotlinx.serialization.Serializable
@Serializable(EncryptedElementSerializer::class)
interface WithReverseSide : EncryptedPassportElement {
val reverseSide: PassportFile?
}

View File

@ -0,0 +1,10 @@
package dev.inmo.tgbotapi.types.passport.encrypted.abstracts
import dev.inmo.tgbotapi.types.passport.encrypted.EncryptedElementSerializer
import dev.inmo.tgbotapi.types.passport.encrypted.PassportFile
import kotlinx.serialization.Serializable
@Serializable(EncryptedElementSerializer::class)
interface WithSelfie : EncryptedPassportElement {
val selfie: PassportFile?
}

View File

@ -1,18 +0,0 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data
import dev.inmo.micro_utils.serialization.base64.Base64StringSerializer
import dev.inmo.tgbotapi.types.emailField
import dev.inmo.tgbotapi.types.hashField
import dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts.WithEmail
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class Email(
@SerialName(emailField)
override val email: String,
@SerialName(hashField)
@Serializable(Base64StringSerializer::class)
override val hash: String
) : WithEmail {
}

View File

@ -1,17 +0,0 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data
import dev.inmo.micro_utils.serialization.base64.Base64StringSerializer
import dev.inmo.tgbotapi.types.dataField
import dev.inmo.tgbotapi.types.passport.EncryptedData
import dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts.WithData
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class EncryptedAddress(
@SerialName(dataField)
@Serializable(Base64StringSerializer::class)
override val data: EncryptedData,
@Serializable(Base64StringSerializer::class)
override val hash: String
) : WithData

View File

@ -1,17 +0,0 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data
import dev.inmo.micro_utils.serialization.base64.Base64StringSerializer
import dev.inmo.tgbotapi.types.dataField
import dev.inmo.tgbotapi.types.passport.EncryptedData
import dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts.WithData
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class EncryptedPersonalDetails(
@SerialName(dataField)
@Serializable(Base64StringSerializer::class)
override val data: EncryptedData,
@Serializable(Base64StringSerializer::class)
override val hash: String
) : WithData

View File

@ -1,18 +0,0 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data
import dev.inmo.micro_utils.serialization.base64.Base64StringSerializer
import dev.inmo.tgbotapi.types.hashField
import dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts.WithPhoneNumber
import dev.inmo.tgbotapi.types.phoneNumberField
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class PhoneNumber(
@SerialName(phoneNumberField)
override val phoneNumber: String,
@SerialName(hashField)
@Serializable(Base64StringSerializer::class)
override val hash: String
) : WithPhoneNumber {
}

View File

@ -1,18 +0,0 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts
import dev.inmo.micro_utils.serialization.base64.Base64StringSerializer
import dev.inmo.tgbotapi.types.passport.encrypted_data.EncryptedElementSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject
@Serializable(EncryptedElementSerializer::class)
interface EncryptedPassportElement {
val hash: String
}
@Serializable(EncryptedElementSerializer::class)
data class UnknownEncryptedPassportElement(
val rawJson: JsonObject,
@Serializable(Base64StringSerializer::class)
override val hash: String
) : EncryptedPassportElement

View File

@ -1,10 +0,0 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts
import dev.inmo.tgbotapi.types.passport.encrypted_data.EncryptedElementSerializer
import dev.inmo.tgbotapi.types.passport.encrypted_data.PassportFile
import kotlinx.serialization.Serializable
@Serializable(EncryptedElementSerializer::class)
interface FilesCollection : EncryptedPassportElement {
val files: List<PassportFile>
}

View File

@ -1,10 +0,0 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts
import dev.inmo.tgbotapi.types.passport.encrypted_data.EncryptedElementSerializer
import dev.inmo.tgbotapi.types.passport.encrypted_data.PassportFile
import kotlinx.serialization.Serializable
@Serializable(EncryptedElementSerializer::class)
interface Translatable : EncryptedPassportElement {
val translations: List<PassportFile>
}

View File

@ -1,10 +0,0 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts
import dev.inmo.tgbotapi.types.passport.EncryptedData
import dev.inmo.tgbotapi.types.passport.encrypted_data.EncryptedElementSerializer
import kotlinx.serialization.Serializable
@Serializable(EncryptedElementSerializer::class)
interface WithData : EncryptedPassportElement {
val data: EncryptedData
}

View File

@ -1,10 +0,0 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts
import dev.inmo.tgbotapi.types.passport.encrypted_data.EncryptedElementSerializer
import dev.inmo.tgbotapi.types.passport.encrypted_data.PassportFile
import kotlinx.serialization.Serializable
@Serializable(EncryptedElementSerializer::class)
interface WithFrontSide : EncryptedPassportElement {
val frontSide: PassportFile?
}

View File

@ -1,10 +0,0 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts
import dev.inmo.tgbotapi.types.passport.encrypted_data.EncryptedElementSerializer
import dev.inmo.tgbotapi.types.passport.encrypted_data.PassportFile
import kotlinx.serialization.Serializable
@Serializable(EncryptedElementSerializer::class)
interface WithReverseSide : EncryptedPassportElement {
val reverseSide: PassportFile?
}

View File

@ -1,10 +0,0 @@
package dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts
import dev.inmo.tgbotapi.types.passport.encrypted_data.EncryptedElementSerializer
import dev.inmo.tgbotapi.types.passport.encrypted_data.PassportFile
import kotlinx.serialization.Serializable
@Serializable(EncryptedElementSerializer::class)
interface WithSelfie : EncryptedPassportElement {
val selfie: PassportFile?
}

View File

@ -1,32 +1,15 @@
package dev.inmo.tgbotapi.utils.passport package dev.inmo.tgbotapi.utils.passport
import dev.inmo.micro_utils.crypto.SourceBytes
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.DownloadFile import dev.inmo.tgbotapi.requests.DownloadFile
import dev.inmo.tgbotapi.requests.get.GetFile import dev.inmo.tgbotapi.requests.get.GetFile
import dev.inmo.tgbotapi.types.passport.encrypted_data.PassportFile import dev.inmo.tgbotapi.types.passport.credentials.EncryptedCredentials
import dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts.WithData import dev.inmo.tgbotapi.types.passport.credentials.EncryptedData
import dev.inmo.tgbotapi.types.passport.encrypted.PassportFile
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
interface Decryptor { interface Decryptor {
fun ByteArray.decrypt(): ByteArray fun decrypt(data: EncryptedData): SourceBytes
} }
suspend fun Decryptor.decrypt(
file: PassportFile,
bot: TelegramBot
): ByteArray {
return bot.execute(
DownloadFile(
bot.execute(
GetFile(file.fileId)
).filePath
)
).decrypt()
}
fun Decryptor.decryptData(
data: WithData
) = nonstrictJsonFormat.decodeFromString(
JsonObject.serializer(),
data.data.encodeToByteArray().decrypt().decodeToString()
)

View File

@ -1,32 +0,0 @@
package dev.inmo.tgbotapi.passport
import dev.inmo.tgbotapi.types.passport.EncryptedAndBase64EncodedData
//actual val privateKey = """-----BEGIN RSA PRIVATE KEY-----
//MIIEowIBAAKCAQEAt0hdC7xyjrRAXxqrd5i06haPfKLdAvRWsPy2yWtYTFom5dBj
//atMUnFKekTwsmhKbRPBoqF7Da0RF+/Y9q9zmZv05+tNz2FEYGJ6o7r/gdAEX+pKs
//Hd84avm9RahGOwbZgcE8r8Md/tg/ZJCSMsVElzM/Gw02+U1uJQE4n/E2AATbRl0M
//oWdyXjh6Zk6HMiTCvhtQOHoMa9yI00wmHVAlZonovZSRQ2mqfwPlbkDhjsDUQMZp
//WcSPQblAd8FLcWsR1Mh86rQl1GxZVWYONaNwoeATe4p6Ng438HCL7jO7nc4jXJwp
//xqwGI9eUYlHolApBeMQK7oEYDTQ+e0iTvFryPQIDAQABAoIBAAnV81BW65rm53Fz
//H/KKGmNZlJeuscefzysuVKzYeuOWDvJUTZGFBF0jPekzXn1iNDzt3d/zPe96uXq9
//CzA26ZJrUno4cMYSDAX+NbiiSWxQRrYmut/bg86R2mtrjWFLi86fzR7tjKWJe1Vt
//QLtCxNyMXn2YJvQYCKopt501t50mjkgR3xM375cfVmpomcZXh1K+z4ZxFVzivjvK
//ZAga3BPQ/hd6dhnwUdB/yFZFao1dDmsvJVjsnjpnWD3uqtciTeg2iqtXVLpaLfbJ
//gWOt5P94uIP5r1+qvyrrPXzUGONm4l+43zgvleEgAXWGxnutsYaFfazVQ6qOVyE7
//fGMQfcECgYEA5Zt1fwTVoYIohq4Do/y5TnNcoj4AajXZU1OutFcPM3aNex16UPBW
//hP7Gakq3TwTKxEILDqOwo86IJuG+lX18kUwaj1f/3T0kDFvE6iLimiPYRNByog4c
//Z5Kwqn+vrnl4ciRDoz7jJsURms2PE7mYV7bndA24Gb0FZJRWiB1xI+0CgYEAzFm7
//uTSyzacTsqorkyUFIwoGgMIE5NDBQNCVhflJcrmuHRYNwxkH9HRCXqyeHKLiNPRa
//zAoBo3WynjActoy0tFJ90qZI1203iT9BMRbPDiZEXnMH4MrWmk7e7poAUsPVKaRr
//hxvHjr2gTOLY0ClolMvnyNxZcZ/jBxAG0WwK3ZECgYEAwSkdmbQZfPwg19zBF05f
//Ho6SmbMLak7O+/jkerbbBPJxZ+eOpVTrlIs5pOYifImNg7oDz1cKHWR8yikTynN9
//PkcF+R2RFTCAiR0S9d5PQFlzccDjD05Lux5/HZC53VA3cd7sQAOB2XXkr5TLD08N
//yI0I/mskPBL23Hymp3ANZKkCgYAO2fqttCnGjnz9ACcYk5ky+biNRQyMAKv65O3p
//BbwTzXDdBkxLwJb2ajikntEC7ceY56VtrNB/q78mhgKgNcuwS0p/s7wZhAOEQwee
//5LR5p8hSQPPyn2tHXbIQDzs0yKzGUP/LmvY+5oMu81Gkl03VephG3dTWUDN0wPJt
//5/dGMQKBgE++3BNLLV8siedqwjhSrRB/KmpbLPtoOUlRJYBfG+oITgl/d/W2NKOg
//C5GztdiZUKlHsvvcYoAAWrgEE3bKg+D7GI15yzAjQQZH6AOgL+CEnunIHBaxEEgG
//RS39yB/kPcn9ZtvcJd9v8myQnQjhco8Z2RUwb6IUIoOBvZlSGhGe
//-----END RSA PRIVATE KEY-----"""
//actual val encryptedLoremIpsum: EncryptedAndBase64EncodedData = "KeuPVezTbMW4MvOGJFTAt34PRaL9iepGb1g4QEi5EQYjKXeXo7RytFOCVx6pW9O/uoMWhl+cX32kNqJVWyK7a22kuhnNT2+aiXqEpuh+madx+LK1zUvGDR1A1Mrf3fFOugcnadCQKICiqvl9cFdqsBkJQOFEs9qj5wiu1F57kekuHLWI7ZnHOojkRNq7l1aCHL0DxcLCfZW5CtWAi8g/zUE5WnGd+vUZ+hqc1vnehDul8JE8YUQbAiIxetzba9XoWouTHYZRZcNCztDbrRBYnq2UCcI5adEwQ3VNcES0lIjRuwn1BBWpvk7VOjqh+4c2tSebDX5AkqrO8XwQYwo8OwvZF+hUXFRK6QLHd4B1JQIdygCaEODG0X353upiEKJXDBqv/ZMXR9KqYZBZEfu48ZM/J6heNjVSOP4TSDrXywJgIOieu8mrQ4d7Or7Twnsu/B+bqS37PvVlfU4wHLl7ehXFj4Kusat6cIrb0R4F/Y3fL4+FcfEsk4ioEAndYBFrc1S11vo/TkcuFnXtqrr181gC5JD5LtsUH6sst36vE/JdL/UwTGqhu+rDUcgvr7FiunkasWBnzCtFs58JJrRycUKPzyKINS16GkY8yYtp7xJXBGPYOFM+J7npcKW7P41j1KceDaUArjph2yIELEXCr8qUZzWXZdrw96Te8gLi99c="

View File

@ -0,0 +1,21 @@
package dev.inmo.tgbotapi.utils.passport
import dev.inmo.micro_utils.crypto.SourceBytes
import dev.inmo.tgbotapi.types.passport.credentials.EncryptedData
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
class AESDecryptor(key: SourceBytes, private val iv: ByteArray) : Decryptor {
private val key = SecretKeySpec(key, "AES");
override fun decrypt(data: EncryptedData): SourceBytes {
return Cipher.getInstance("AES/CBC/NOPADDING").run {
init(Cipher.DECRYPT_MODE, key, IvParameterSpec(this@AESDecryptor.iv))
val decryptedCredentials = doFinal(data)
val padding = decryptedCredentials.first()
decryptedCredentials.copyOfRange(padding.toInt(), decryptedCredentials.size)
}
}
}

View File

@ -0,0 +1,29 @@
package dev.inmo.tgbotapi.utils.passport
import dev.inmo.micro_utils.crypto.decodeBase64
import dev.inmo.tgbotapi.types.passport.credentials.DecryptedCredentials
import dev.inmo.tgbotapi.types.passport.credentials.EncryptedCredentials
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
import java.security.*
import java.security.spec.PKCS8EncodedKeySpec
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
private val regexToRemoveFromKey = Regex("(-----(BEGIN|END) ((?:.*? KEY)|CERTIFICATE)-----|[\\s])")
fun EncryptedCredentials.decryptWithPKCS8PrivateKey(privateKey: PrivateKey): DecryptedCredentials {
val decrypted = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding").run {
init(Cipher.DECRYPT_MODE, privateKey)
doFinal(secret)
}
val dataDecryptor = (decrypted to hash).createDecryptor()
val decryptedCredentials = dataDecryptor.decrypt(data).decodeToString()
return nonstrictJsonFormat.decodeFromString(DecryptedCredentials.serializer(), decryptedCredentials)
}
fun EncryptedCredentials.decryptWithPKCS8PrivateKey(key: String) = decryptWithPKCS8PrivateKey(
KeyFactory.getInstance("RSA").generatePrivate(
PKCS8EncodedKeySpec(key.replace(regexToRemoveFromKey, "").decodeBase64())
)
)

View File

@ -1,39 +0,0 @@
package dev.inmo.tgbotapi.utils.passport
import dev.inmo.micro_utils.crypto.decodeBase64
import java.security.KeyFactory
import java.security.interfaces.RSAPrivateKey
import java.security.spec.PKCS8EncodedKeySpec
import javax.crypto.Cipher
private val regexToRemoveFromKey = Regex("(-----(BEGIN|END) ((?:.*? KEY)|CERTIFICATE)-----|[\\s])")
/**
* @param key PKCS8
*/
class PKCS8Decryptor (key: String): Decryptor {
private val privateKey: RSAPrivateKey = KeyFactory.getInstance("RSA").generatePrivate(
PKCS8EncodedKeySpec(key.replace(regexToRemoveFromKey, "").decodeBase64())
) as RSAPrivateKey
private val chunkSize: Int = privateKey.modulus.bitLength() / 8
override fun ByteArray.decrypt(): ByteArray {
return Cipher.getInstance("RSA/ECB/PKCS1Padding").run {
init(Cipher.DECRYPT_MODE, privateKey)
(0 until size step chunkSize).flatMap {
val firstIndex = it
val lastIndexExclusive = if (it + chunkSize > size) {
size
} else {
it + chunkSize
}
doFinal(copyOfRange(firstIndex, lastIndexExclusive)).toList()
}.toByteArray()
}
}
}
fun Decryptor(key: String) = PKCS8Decryptor(key)
inline fun <T> doWithDecryptor(decryptor: Decryptor, crossinline block: Decryptor.() -> T) = decryptor.run(block)
inline fun <T> doWithDecryptor(key: String, crossinline block: Decryptor.() -> T) = doWithDecryptor(Decryptor(key), block)

View File

@ -0,0 +1,28 @@
package dev.inmo.tgbotapi.utils.passport
import dev.inmo.micro_utils.crypto.SourceBytes
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.DownloadFile
import dev.inmo.tgbotapi.requests.get.GetFile
import dev.inmo.tgbotapi.types.passport.credentials.*
import dev.inmo.tgbotapi.types.passport.encrypted.PassportFile
fun EndDataCredentials.decryptData(
bytes: EncryptedData
): SourceBytes {
return createDecryptor().decrypt(bytes)
}
fun FileCredentials.decryptFile(
fileBytes: ByteArray
): SourceBytes {
return createDecryptor().decrypt(fileBytes)
}
suspend fun FileCredentials.decryptFile(
bot: TelegramBot,
passportFile: PassportFile
): SourceBytes {
val pathedFile = bot.execute(GetFile(passportFile.fileId))
val bytes = bot.execute(DownloadFile(pathedFile.filePath))
return decryptFile(bytes)
}

View File

@ -0,0 +1,15 @@
package dev.inmo.tgbotapi.utils.passport
import dev.inmo.micro_utils.crypto.SourceBytes
import dev.inmo.tgbotapi.types.passport.credentials.EndDataCredentials
import java.security.MessageDigest
fun Pair<SourceBytes, SourceBytes>.createDecryptor(): Decryptor {
val secretHash = MessageDigest.getInstance("SHA-512").digest(first + second)
val key = secretHash.copyOf(32)
val iv = secretHash.copyOfRange(32, 48)
return AESDecryptor(key, iv)
}
fun EndDataCredentials.createDecryptor() = (secret to hash).createDecryptor()

View File

@ -0,0 +1,15 @@
package dev.inmo.tgbotapi.utils.passport
import dev.inmo.tgbotapi.types.passport.PassportData
import dev.inmo.tgbotapi.types.passport.decrypted.SecureData
import java.security.PrivateKey
inline fun <T> PassportData.doInDecryptionContextWithPKCS8Key(
pkcs8Key: PrivateKey,
expectedNonce: String? = null,
crossinline block: SecureData.() -> T
): T {
val decryptedCredentials = credentials.decryptWithPKCS8PrivateKey(pkcs8Key)
expectedNonce ?.let { require(expectedNonce == decryptedCredentials.nonce) }
return decryptedCredentials.secureData.run(block)
}

View File

@ -1,52 +0,0 @@
package dev.inmo.tgbotapi.passport
import dev.inmo.micro_utils.crypto.decodeBase64
import dev.inmo.tgbotapi.utils.passport.Decryptor
import dev.inmo.tgbotapi.utils.passport.doWithDecryptor
import kotlin.test.Test
import kotlin.test.assertEquals
//expect val privateKey: String
//expect val encryptedLoremIpsum: EncryptedAndBase64EncodedData
val privateKey: String = """-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCaaMFkmMBi6Vl5
vzy7wQjoZNLN+e9e6Lb/WBekJxfbNMt+EN9Zv7xT9xzfY68DX7v0uGoLcAqS5Mh5
8ELiJbzg4O8dbxkggt0G+kxcbT+a3ofm1Aqhr+LkpsFh5qbLqbAHSQJAF0HPqrAc
5c6MoQVTZlWGU/j3enCcUFo7Jpsi8La6MqYboF5xGwGEZ9tOA6rMDSekr5Rdm637
D/w4h284UX7VnqPdpZ/943VK2qvmPjm8HkFSxkSAB8RHlFyjazzm9FNOcVRGLynv
/cq7mWgyxt5nqiCG7w+lFNAFNQNvAO0rfeiTJbEzubquu4Mg31QrvLIuz+fUbsGk
ipfpN1czAgMBAAECggEAPlAoO8CpY0FoqolSqTKttZt6t0U2JMclksaqQ8TDC+Oy
e52zhTSre/ct37kK2AG6iHgj05nTqpRJk2wykbFJGDeuR+Kd8VDeggJg7qvoD0fe
8HiCEd45Yq0pPaknhulj8Iy2K8c29+eaSw8y2+3fiFi0CxG4V6dB6tNClrxtvxtl
IE85Utzmk4PLTCs010zxNVm+FwrvqlpjjhspljzleUuWE1KuldO9tNSlwUUfBr4i
BJJn4jDkQMloXoM/ArZEp7mn57N9+ZuEgVjRMCpRGEAbQI+aLCznBB1kCOY7WL8S
CwkP++SvcptaUpOjoXZZyuGU4CgBnu0+40ORbNchgQKBgQDLIbB9+WHDcZAn1g6M
8jaNDRU4HGu5vJSajFQK8Uaczg87hAxmk6R1GF0LOyoadaVmD5ax93mQxWSE/4hT
wyAPaQOFl7A/i1k/Dx/kURjRwF1sLWDFdMo/8t5bXumzrzb1bHYnHPS7S0lBAU+X
SrbIw+hv69aKawcQqdd54S1OBwKBgQDCmMarwMVn4xnOh+DOuLS4IQzPT84WgzH+
wKw55hZGMqZ4S3JRVv256daweEbKAeR5NCccPmir0H86jwUW6WFAtxqfPWF4piVi
UD6DrUt0gWwzMGy3kbAp0hLBtsQRp/41mKuAXkvMVQ2ysInn6lmHhZvjduK8lvKh
fMRDMjxidQKBgFiciK5blI86wgTutwg7PRrI40HH/CJZJoZIwvzHBeOvbCutTe+N
ZoeCKkyU8af7PDzKfhWCfHBv+4qdIi5QB3NRfyzO4B7IPhVpFqN10RrnDJn9LaLV
cMj2vJMlU1OEErh7KQuk8QmnLPyDguHfwN7Rv1rbiYp2Z+2X+Zx8Y1QPAoGBAJIf
nq/CJXoJMou/xLP2Rt4tEy1pQ9vr0FL341vmxrsXtaGHJeSmagh861XAO4fdO+83
llbDFl5ORft3Ad9eiETMOhVxRgwO1uuoTgkazBpERTd7GWgO4jXFJYiI8VpAx8b/
SWkvZcOd6pdPsX6Qn4IAdjqsPz5WKwPQaJ/8zRMxAoGAGaOuyXaFZNl8IeTGYMDL
OEg9BHa+Du8jSv0vL/fCN2s/2TcvSa9uEnv8KHz59JHevvxoDNbQYlN8Ge8adFv4
xZYQ3h/qh2ohnTUfrG4hcFUVBuv5HBdwgWhVFm5v98KQsqVzGfKorN2DemEv3/au
PFGkuu4lCPeDqu5u0dBojoA=
-----END PRIVATE KEY-----"""
val encryptedLoremIpsum = "KeuPVezTbMW4MvOGJFTAt34PRaL9iepGb1g4QEi5EQYjKXeXo7RytFOCVx6pW9O/uoMWhl+cX32kNqJVWyK7a22kuhnNT2+aiXqEpuh+madx+LK1zUvGDR1A1Mrf3fFOugcnadCQKICiqvl9cFdqsBkJQOFEs9qj5wiu1F57kekuHLWI7ZnHOojkRNq7l1aCHL0DxcLCfZW5CtWAi8g/zUE5WnGd+vUZ+hqc1vnehDul8JE8YUQbAiIxetzba9XoWouTHYZRZcNCztDbrRBYnq2UCcI5adEwQ3VNcES0lIjRuwn1BBWpvk7VOjqh+4c2tSebDX5AkqrO8XwQYwo8OwvZF+hUXFRK6QLHd4B1JQIdygCaEODG0X353upiEKJXDBqv/ZMXR9KqYZBZEfu48ZM/J6heNjVSOP4TSDrXywJgIOieu8mrQ4d7Or7Twnsu/B+bqS37PvVlfU4wHLl7ehXFj4Kusat6cIrb0R4F/Y3fL4+FcfEsk4ioEAndYBFrc1S11vo/TkcuFnXtqrr181gC5JD5LtsUH6sst36vE/JdL/UwTGqhu+rDUcgvr7FiunkasWBnzCtFs58JJrRycUKPzyKINS16GkY8yYtp7xJXBGPYOFM+J7npcKW7P41j1KceDaUArjph2yIELEXCr8qUZzWXZdrw96Te8gLi99c="
class DecryptionTest {
val inputText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
@Test
fun testThatDecryptionIsWorkingCorrectly() {
doWithDecryptor(privateKey) {
val decrypted = encryptedLoremIpsum.decodeBase64().decrypt().decodeToString()
assertEquals(inputText, decrypted)
}
}
}

View File

@ -0,0 +1,45 @@
package dev.inmo.tgbotapi.extensions.api.passport
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.SetPassportDataErrors
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.message.PassportMessage
import dev.inmo.tgbotapi.types.passport.PassportData
import dev.inmo.tgbotapi.types.passport.PassportElementError
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.EncryptedPassportElement
import dev.inmo.tgbotapi.utils.passport.Decryptor
suspend fun TelegramBot.setPassportDataErrors(
userId: UserId,
errors: List<PassportElementError>
) = execute(SetPassportDataErrors(userId, errors))
suspend fun TelegramBot.setPassportDataErrors(
user: User,
errors: List<PassportElementError>
) = setPassportDataErrors(user.id, errors)
suspend fun TelegramBot.setPassportDataErrors(
userId: UserId,
passportData: PassportData,
decryptor: Decryptor,
mapper: suspend Decryptor.(EncryptedPassportElement) -> PassportElementError
): Boolean = setPassportDataErrors(
userId,
passportData.data.map { decryptor.mapper(it) }.also {
if (it.isEmpty()) {
return@setPassportDataErrors false
}
}
)
suspend fun TelegramBot.setPassportDataErrors(
user: User,
passportData: PassportData,
decryptor: Decryptor,
mapper: suspend Decryptor.(EncryptedPassportElement) -> PassportElementError
) = setPassportDataErrors(user.id, passportData, decryptor, mapper)
suspend fun TelegramBot.setPassportDataErrors(
passportMessage: PassportMessage,
decryptor: Decryptor,
mapper: suspend Decryptor.(EncryptedPassportElement) -> PassportElementError
) = setPassportDataErrors(passportMessage.user, passportMessage.passportData, decryptor, mapper)

View File

@ -0,0 +1,54 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
import dev.inmo.tgbotapi.extensions.utils.*
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.types.message.PassportMessage
import dev.inmo.tgbotapi.types.passport.PassportData
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.EncryptedPassportElement
import dev.inmo.tgbotapi.utils.RiskFeature
import kotlinx.coroutines.flow.toList
typealias PassportMessageMapper = suspend PassportMessage.() -> PassportData
@RiskFeature("Do not use this message directly, use waitPassportMessagesWith or waitAnyPassportMessages instead")
suspend fun <O> BehaviourContext.waitPassportMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
count: Int = 1,
mapper: suspend PassportMessage.() -> O?
): List<O> = expectFlow(
initRequest,
count,
errorFactory
) {
it.asMessageUpdate() ?.data ?.asPassportMessage() ?.mapper().let(::listOfNotNull)
}.toList().toList()
suspend inline fun <reified T : EncryptedPassportElement> BehaviourContext.waitPassportMessagesWith(
count: Int = 1,
initRequest: Request<*>? = null,
noinline errorFactory: NullableRequestBuilder<*> = { null },
noinline filter: PassportMessageMapper? = null
) : List<PassportData> = waitPassportMessages(
initRequest,
errorFactory,
count
) {
if (passportData.data.any { it is T }) {
if (filter == null) {
passportData
} else {
filter(this)
}
} else {
null
}
}
suspend fun BehaviourContext.waitAnyPassportMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
count: Int = 1,
filter: PassportMessageMapper? = null
) = waitPassportMessagesWith<EncryptedPassportElement>(count, initRequest, errorFactory, filter)

View File

@ -0,0 +1,42 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow
import dev.inmo.tgbotapi.extensions.utils.*
import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat
import dev.inmo.tgbotapi.types.message.PassportMessage
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.EncryptedPassportElement
suspend inline fun <reified T : EncryptedPassportElement> BehaviourContext.onPassportMessageWith(
includeFilterByChatInBehaviourSubContext: Boolean = true,
noinline additionalFilter: (suspend (PassportMessage) -> Boolean)? = null,
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, PassportMessage>
) = flowsUpdatesFilter.expectFlow(bot) {
it.asMessageUpdate() ?.data ?.asPassportMessage() ?.let { message ->
if (message.passportData.data.any { it is T }) {
if (additionalFilter == null || additionalFilter(message)) message else null
} else {
null
}
}.let(::listOfNotNull)
}.subscribeSafelyWithoutExceptions(scope) { triggerMessage ->
doInSubContextWithUpdatesFilter(
updatesFilter = if (includeFilterByChatInBehaviourSubContext) {
{ it.sourceChat() ?.id ?.chatId == triggerMessage.chat.id.chatId }
} else null
) {
scenarioReceiver(triggerMessage)
}
}
suspend fun BehaviourContext.onPassportMessage(
includeFilterByChatInBehaviourSubContext: Boolean = true,
additionalFilter: (suspend (PassportMessage) -> Boolean)? = null,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, PassportMessage>
) = onPassportMessageWith<EncryptedPassportElement>(
includeFilterByChatInBehaviourSubContext,
additionalFilter,
scenarioReceiver
)

View File

@ -37,6 +37,9 @@ import dev.inmo.tgbotapi.types.message.content.*
import dev.inmo.tgbotapi.types.message.content.abstracts.* import dev.inmo.tgbotapi.types.message.content.abstracts.*
import dev.inmo.tgbotapi.types.message.content.media.* import dev.inmo.tgbotapi.types.message.content.media.*
import dev.inmo.tgbotapi.types.message.payments.InvoiceContent import dev.inmo.tgbotapi.types.message.payments.InvoiceContent
import dev.inmo.tgbotapi.types.passport.*
import dev.inmo.tgbotapi.types.passport.encrypted.*
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.*
import dev.inmo.tgbotapi.types.polls.* import dev.inmo.tgbotapi.types.polls.*
import dev.inmo.tgbotapi.types.update.* import dev.inmo.tgbotapi.types.update.*
import dev.inmo.tgbotapi.types.update.MediaGroupUpdates.* import dev.inmo.tgbotapi.types.update.MediaGroupUpdates.*
@ -156,6 +159,182 @@ inline fun CallbackQuery.asUnknownCallbackQueryType(): UnknownCallbackQueryType?
@PreviewFeature @PreviewFeature
inline fun CallbackQuery.requireUnknownCallbackQueryType(): UnknownCallbackQueryType = this as UnknownCallbackQueryType inline fun CallbackQuery.requireUnknownCallbackQueryType(): UnknownCallbackQueryType = this as UnknownCallbackQueryType
@PreviewFeature @PreviewFeature
inline fun PassportElementError.asPassportElementErrorDataField(): PassportElementErrorDataField? = this as? PassportElementErrorDataField
@PreviewFeature
inline fun PassportElementError.requirePassportElementErrorDataField(): PassportElementErrorDataField = this as PassportElementErrorDataField
@PreviewFeature
inline fun PassportElementError.asPassportElementErrorFile(): PassportElementErrorFile? = this as? PassportElementErrorFile
@PreviewFeature
inline fun PassportElementError.requirePassportElementErrorFile(): PassportElementErrorFile = this as PassportElementErrorFile
@PreviewFeature
inline fun PassportElementError.asPassportElementErrorFiles(): PassportElementErrorFiles? = this as? PassportElementErrorFiles
@PreviewFeature
inline fun PassportElementError.requirePassportElementErrorFiles(): PassportElementErrorFiles = this as PassportElementErrorFiles
@PreviewFeature
inline fun PassportElementError.asPassportElementErrorFrontSide(): PassportElementErrorFrontSide? = this as? PassportElementErrorFrontSide
@PreviewFeature
inline fun PassportElementError.requirePassportElementErrorFrontSide(): PassportElementErrorFrontSide = this as PassportElementErrorFrontSide
@PreviewFeature
inline fun PassportElementError.asPassportElementErrorReverseSide(): PassportElementErrorReverseSide? = this as? PassportElementErrorReverseSide
@PreviewFeature
inline fun PassportElementError.requirePassportElementErrorReverseSide(): PassportElementErrorReverseSide = this as PassportElementErrorReverseSide
@PreviewFeature
inline fun PassportElementError.asPassportElementErrorSelfie(): PassportElementErrorSelfie? = this as? PassportElementErrorSelfie
@PreviewFeature
inline fun PassportElementError.requirePassportElementErrorSelfie(): PassportElementErrorSelfie = this as PassportElementErrorSelfie
@PreviewFeature
inline fun PassportElementError.asPassportElementErrorTranslationFile(): PassportElementErrorTranslationFile? = this as? PassportElementErrorTranslationFile
@PreviewFeature
inline fun PassportElementError.requirePassportElementErrorTranslationFile(): PassportElementErrorTranslationFile = this as PassportElementErrorTranslationFile
@PreviewFeature
inline fun PassportElementError.asPassportElementErrorTranslationFiles(): PassportElementErrorTranslationFiles? = this as? PassportElementErrorTranslationFiles
@PreviewFeature
inline fun PassportElementError.requirePassportElementErrorTranslationFiles(): PassportElementErrorTranslationFiles = this as PassportElementErrorTranslationFiles
@PreviewFeature
inline fun PassportElementError.asPassportElementErrorUnspecified(): PassportElementErrorUnspecified? = this as? PassportElementErrorUnspecified
@PreviewFeature
inline fun PassportElementError.requirePassportElementErrorUnspecified(): PassportElementErrorUnspecified = this as PassportElementErrorUnspecified
@PreviewFeature
inline fun PassportElementError.asPassportElementFileError(): PassportElementFileError? = this as? PassportElementFileError
@PreviewFeature
inline fun PassportElementError.requirePassportElementFileError(): PassportElementFileError = this as PassportElementFileError
@PreviewFeature
inline fun PassportElementError.asPassportElementFilesError(): PassportElementFilesError? = this as? PassportElementFilesError
@PreviewFeature
inline fun PassportElementError.requirePassportElementFilesError(): PassportElementFilesError = this as PassportElementFilesError
@PreviewFeature
inline fun PassportElementError.asPassportMultipleElementsError(): PassportMultipleElementsError? = this as? PassportMultipleElementsError
@PreviewFeature
inline fun PassportElementError.requirePassportMultipleElementsError(): PassportMultipleElementsError = this as PassportMultipleElementsError
@PreviewFeature
inline fun PassportElementError.asPassportSingleElementError(): PassportSingleElementError? = this as? PassportSingleElementError
@PreviewFeature
inline fun PassportElementError.requirePassportSingleElementError(): PassportSingleElementError = this as PassportSingleElementError
@PreviewFeature
inline fun PassportElementError.asUnknownPassportElementError(): UnknownPassportElementError? = this as? UnknownPassportElementError
@PreviewFeature
inline fun PassportElementError.requireUnknownPassportElementError(): UnknownPassportElementError = this as UnknownPassportElementError
@PreviewFeature
inline fun EncryptedPassportElement.asBankStatement(): BankStatement? = this as? BankStatement
@PreviewFeature
inline fun EncryptedPassportElement.requireBankStatement(): BankStatement = this as BankStatement
@PreviewFeature
inline fun EncryptedPassportElement.asCommonPassport(): CommonPassport? = this as? CommonPassport
@PreviewFeature
inline fun EncryptedPassportElement.requireCommonPassport(): CommonPassport = this as CommonPassport
@PreviewFeature
inline fun EncryptedPassportElement.asDriverLicense(): DriverLicense? = this as? DriverLicense
@PreviewFeature
inline fun EncryptedPassportElement.requireDriverLicense(): DriverLicense = this as DriverLicense
@PreviewFeature
inline fun EncryptedPassportElement.asEmail(): Email? = this as? Email
@PreviewFeature
inline fun EncryptedPassportElement.requireEmail(): Email = this as Email
@PreviewFeature
inline fun EncryptedPassportElement.asEncryptedAddress(): EncryptedAddress? = this as? EncryptedAddress
@PreviewFeature
inline fun EncryptedPassportElement.requireEncryptedAddress(): EncryptedAddress = this as EncryptedAddress
@PreviewFeature
inline fun EncryptedPassportElement.asEncryptedPersonalDetails(): EncryptedPersonalDetails? = this as? EncryptedPersonalDetails
@PreviewFeature
inline fun EncryptedPassportElement.requireEncryptedPersonalDetails(): EncryptedPersonalDetails = this as EncryptedPersonalDetails
@PreviewFeature
inline fun EncryptedPassportElement.asIdentityCard(): IdentityCard? = this as? IdentityCard
@PreviewFeature
inline fun EncryptedPassportElement.requireIdentityCard(): IdentityCard = this as IdentityCard
@PreviewFeature
inline fun EncryptedPassportElement.asInternalPassport(): InternalPassport? = this as? InternalPassport
@PreviewFeature
inline fun EncryptedPassportElement.requireInternalPassport(): InternalPassport = this as InternalPassport
@PreviewFeature
inline fun EncryptedPassportElement.asPassport(): Passport? = this as? Passport
@PreviewFeature
inline fun EncryptedPassportElement.requirePassport(): Passport = this as Passport
@PreviewFeature
inline fun EncryptedPassportElement.asPassportRegistration(): PassportRegistration? = this as? PassportRegistration
@PreviewFeature
inline fun EncryptedPassportElement.requirePassportRegistration(): PassportRegistration = this as PassportRegistration
@PreviewFeature
inline fun EncryptedPassportElement.asPhoneNumber(): PhoneNumber? = this as? PhoneNumber
@PreviewFeature
inline fun EncryptedPassportElement.requirePhoneNumber(): PhoneNumber = this as PhoneNumber
@PreviewFeature
inline fun EncryptedPassportElement.asRentalAgreement(): RentalAgreement? = this as? RentalAgreement
@PreviewFeature
inline fun EncryptedPassportElement.requireRentalAgreement(): RentalAgreement = this as RentalAgreement
@PreviewFeature
inline fun EncryptedPassportElement.asTemporaryRegistration(): TemporaryRegistration? = this as? TemporaryRegistration
@PreviewFeature
inline fun EncryptedPassportElement.requireTemporaryRegistration(): TemporaryRegistration = this as TemporaryRegistration
@PreviewFeature
inline fun EncryptedPassportElement.asTranslatableFilesCollection(): TranslatableFilesCollection? = this as? TranslatableFilesCollection
@PreviewFeature
inline fun EncryptedPassportElement.requireTranslatableFilesCollection(): TranslatableFilesCollection = this as TranslatableFilesCollection
@PreviewFeature
inline fun EncryptedPassportElement.asTranslatableIDDocument(): TranslatableIDDocument? = this as? TranslatableIDDocument
@PreviewFeature
inline fun EncryptedPassportElement.requireTranslatableIDDocument(): TranslatableIDDocument = this as TranslatableIDDocument
@PreviewFeature
inline fun EncryptedPassportElement.asUtilityBill(): UtilityBill? = this as? UtilityBill
@PreviewFeature
inline fun EncryptedPassportElement.requireUtilityBill(): UtilityBill = this as UtilityBill
@PreviewFeature
inline fun EncryptedPassportElement.asFilesCollection(): FilesCollection? = this as? FilesCollection
@PreviewFeature
inline fun EncryptedPassportElement.requireFilesCollection(): FilesCollection = this as FilesCollection
@PreviewFeature
inline fun EncryptedPassportElement.asTranslatable(): Translatable? = this as? Translatable
@PreviewFeature
inline fun EncryptedPassportElement.requireTranslatable(): Translatable = this as Translatable
@PreviewFeature
inline fun EncryptedPassportElement.asUnknownEncryptedPassportElement(): UnknownEncryptedPassportElement? = this as? UnknownEncryptedPassportElement
@PreviewFeature
inline fun EncryptedPassportElement.requireUnknownEncryptedPassportElement(): UnknownEncryptedPassportElement = this as UnknownEncryptedPassportElement
@PreviewFeature
inline fun EncryptedPassportElement.asWithData(): WithData? = this as? WithData
@PreviewFeature
inline fun EncryptedPassportElement.requireWithData(): WithData = this as WithData
@PreviewFeature
inline fun EncryptedPassportElement.asWithEmail(): WithEmail? = this as? WithEmail
@PreviewFeature
inline fun EncryptedPassportElement.requireWithEmail(): WithEmail = this as WithEmail
@PreviewFeature
inline fun EncryptedPassportElement.asWithFrontSide(): WithFrontSide? = this as? WithFrontSide
@PreviewFeature
inline fun EncryptedPassportElement.requireWithFrontSide(): WithFrontSide = this as WithFrontSide
@PreviewFeature
inline fun EncryptedPassportElement.asWithPhoneNumber(): WithPhoneNumber? = this as? WithPhoneNumber
@PreviewFeature
inline fun EncryptedPassportElement.requireWithPhoneNumber(): WithPhoneNumber = this as WithPhoneNumber
@PreviewFeature
inline fun EncryptedPassportElement.asWithReverseSide(): WithReverseSide? = this as? WithReverseSide
@PreviewFeature
inline fun EncryptedPassportElement.requireWithReverseSide(): WithReverseSide = this as WithReverseSide
@PreviewFeature
inline fun EncryptedPassportElement.asWithSelfie(): WithSelfie? = this as? WithSelfie
@PreviewFeature
inline fun EncryptedPassportElement.requireWithSelfie(): WithSelfie = this as WithSelfie
@PreviewFeature
inline fun Message.asAnonymousGroupMessageImpl(): AnonymousGroupMessageImpl<MessageContent>? = this as? AnonymousGroupMessageImpl<MessageContent>
@PreviewFeature
inline fun Message.requireAnonymousGroupMessageImpl(): AnonymousGroupMessageImpl<MessageContent> = this as AnonymousGroupMessageImpl<MessageContent>
@PreviewFeature
inline fun Message.asChannelMessageImpl(): ChannelMessageImpl<MessageContent>? = this as? ChannelMessageImpl<MessageContent>
@PreviewFeature
inline fun Message.requireChannelMessageImpl(): ChannelMessageImpl<MessageContent> = this as ChannelMessageImpl<MessageContent>
@PreviewFeature
inline fun Message.asFromChannelGroupMessageImpl(): FromChannelGroupMessageImpl<MessageContent>? = this as? FromChannelGroupMessageImpl<MessageContent>
@PreviewFeature
inline fun Message.requireFromChannelGroupMessageImpl(): FromChannelGroupMessageImpl<MessageContent> = this as FromChannelGroupMessageImpl<MessageContent>
@PreviewFeature
inline fun Message.asPassportMessage(): PassportMessage? = this as? PassportMessage
@PreviewFeature
inline fun Message.requirePassportMessage(): PassportMessage = this as PassportMessage
@PreviewFeature
inline fun Message.asPrivateMessageImpl(): PrivateMessageImpl<MessageContent>? = this as? PrivateMessageImpl<MessageContent>
@PreviewFeature
inline fun Message.requirePrivateMessageImpl(): PrivateMessageImpl<MessageContent> = this as PrivateMessageImpl<MessageContent>
@PreviewFeature
inline fun Message.asChannelEventMessage(): ChannelEventMessage<ChannelEvent>? = this as? ChannelEventMessage<ChannelEvent> inline fun Message.asChannelEventMessage(): ChannelEventMessage<ChannelEvent>? = this as? ChannelEventMessage<ChannelEvent>
@PreviewFeature @PreviewFeature
inline fun Message.requireChannelEventMessage(): ChannelEventMessage<ChannelEvent> = this as ChannelEventMessage<ChannelEvent> inline fun Message.requireChannelEventMessage(): ChannelEventMessage<ChannelEvent> = this as ChannelEventMessage<ChannelEvent>