diff --git a/CHANGELOG.md b/CHANGELOG.md index f9f7484dda..b9f80096ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ * `Klock`: `2.2.0` -> `2.3.1` * `Ktor`: `1.6.1` -> `1.6.2` * `MicroUtils`: `0.5.16` -> `0.5.18` +* `Core`: + * Support of strongly-typed ietf language codes has been added * `API`: * New extension `TelegramBot#downloadFile` for any `MediaContent` * `Behaviour Builder`: diff --git a/tgbotapi.core/build.gradle b/tgbotapi.core/build.gradle index 1948d03bc0..83582016f5 100644 --- a/tgbotapi.core/build.gradle +++ b/tgbotapi.core/build.gradle @@ -51,6 +51,7 @@ kotlin { api "dev.inmo:micro_utils.serialization.base64:$micro_utils_version" api "dev.inmo:micro_utils.serialization.encapsulator:$micro_utils_version" api "dev.inmo:micro_utils.serialization.typed_serializer:$micro_utils_version" + api "dev.inmo:micro_utils.language_codes:$micro_utils_version" api "io.ktor:ktor-client-core:$ktor_version" } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/WithLanguageCode.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/WithLanguageCode.kt new file mode 100644 index 0000000000..d59d9c9cce --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/WithLanguageCode.kt @@ -0,0 +1,17 @@ +package dev.inmo.tgbotapi.CommonAbstracts + +import dev.inmo.micro_utils.language_codes.IetfLanguageCode + +interface WithOptionalLanguageCode { + val ietfLanguageCode: IetfLanguageCode? + + val languageCode: String? + get() = ietfLanguageCode ?.code +} + +interface WithLanguageCode : WithOptionalLanguageCode { + override val ietfLanguageCode: IetfLanguageCode + + override val languageCode: String + get() = ietfLanguageCode.code +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/BotCommand.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/BotCommand.kt index bc6b7cac0b..e5fb89c6c3 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/BotCommand.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/BotCommand.kt @@ -1,9 +1,9 @@ package dev.inmo.tgbotapi.requests.bot +import dev.inmo.tgbotapi.CommonAbstracts.WithOptionalLanguageCode import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest import dev.inmo.tgbotapi.types.commands.BotCommandScope -sealed interface MyCommandsRequest : SimpleRequest { +sealed interface MyCommandsRequest : SimpleRequest, WithOptionalLanguageCode { val scope: BotCommandScope - val languageCode: String? } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/DeleteMyCommands.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/DeleteMyCommands.kt index 867b5fc978..61b01180cb 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/DeleteMyCommands.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/DeleteMyCommands.kt @@ -1,8 +1,9 @@ package dev.inmo.tgbotapi.requests.bot +import dev.inmo.micro_utils.language_codes.IetfLanguageCode +import dev.inmo.micro_utils.language_codes.IetfLanguageCodeSerializer +import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.commands.* -import dev.inmo.tgbotapi.types.languageCodeField -import dev.inmo.tgbotapi.types.scopeField import kotlinx.serialization.* import kotlinx.serialization.builtins.serializer @@ -12,11 +13,20 @@ data class DeleteMyCommands( @Serializable(BotCommandScopeSerializer::class) override val scope: BotCommandScope = BotCommandScopeDefault, @SerialName(languageCodeField) - override val languageCode: String? = null + @Serializable(IetfLanguageCodeSerializer::class) + override val ietfLanguageCode: IetfLanguageCode? = null ) : MyCommandsRequest { override fun method(): String = "deleteMyCommands" override val requestSerializer: SerializationStrategy = serializer() override val resultDeserializer: DeserializationStrategy = Boolean.serializer() + constructor( + scope: BotCommandScope = BotCommandScopeDefault, + languageCode: String? + ) : this( + scope, + languageCode ?.let(::IetfLanguageCode) + ) + companion object : MyCommandsRequest by DeleteMyCommands() } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/GetMyCommands.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/GetMyCommands.kt index 31b8fe194a..511fc9e33f 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/GetMyCommands.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/GetMyCommands.kt @@ -1,5 +1,7 @@ package dev.inmo.tgbotapi.requests.bot +import dev.inmo.micro_utils.language_codes.IetfLanguageCode +import dev.inmo.micro_utils.language_codes.IetfLanguageCodeSerializer import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.commands.* import kotlinx.serialization.* @@ -13,7 +15,8 @@ data class GetMyCommands( @Serializable(BotCommandScopeSerializer::class) override val scope: BotCommandScope = BotCommandScopeDefault, @SerialName(languageCodeField) - override val languageCode: String? = null + @Serializable(IetfLanguageCodeSerializer::class) + override val ietfLanguageCode: IetfLanguageCode? = null ) : MyCommandsRequest> { override fun method(): String = "getMyCommands" override val resultDeserializer: DeserializationStrategy> @@ -21,5 +24,13 @@ data class GetMyCommands( override val requestSerializer: SerializationStrategy<*> get() = serializer() + constructor( + scope: BotCommandScope = BotCommandScopeDefault, + languageCode: String? + ) : this( + scope, + languageCode ?.let(::IetfLanguageCode) + ) + companion object : MyCommandsRequest> by GetMyCommands() } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/SetMyCommands.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/SetMyCommands.kt index 4f926840e2..6df10c13b1 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/SetMyCommands.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/SetMyCommands.kt @@ -1,5 +1,7 @@ package dev.inmo.tgbotapi.requests.bot +import dev.inmo.micro_utils.language_codes.IetfLanguageCode +import dev.inmo.micro_utils.language_codes.IetfLanguageCodeSerializer import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.commands.* import kotlinx.serialization.* @@ -13,7 +15,8 @@ class SetMyCommands( @Serializable(BotCommandScopeSerializer::class) override val scope: BotCommandScope = BotCommandScopeDefault, @SerialName(languageCodeField) - override val languageCode: String? = null + @Serializable(IetfLanguageCodeSerializer::class) + override val ietfLanguageCode: IetfLanguageCode? = null ) : MyCommandsRequest { override fun method(): String = "setMyCommands" override val resultDeserializer: DeserializationStrategy @@ -21,6 +24,16 @@ class SetMyCommands( override val requestSerializer: SerializationStrategy<*> get() = serializer() + constructor( + commands: List, + scope: BotCommandScope = BotCommandScopeDefault, + languageCode: String? + ) : this( + commands, + scope, + languageCode ?.let(::IetfLanguageCode) + ) + init { if (commands.size !in botCommandsLimit) { error("Bot commands list size able to be in range $botCommandsLimit, but incoming size is ${commands.size}") diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/User.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/User.kt index bcc2ea2875..b8774ea67c 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/User.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/User.kt @@ -1,5 +1,8 @@ package dev.inmo.tgbotapi.types +import dev.inmo.micro_utils.language_codes.IetfLanguageCode +import dev.inmo.micro_utils.language_codes.IetfLanguageCodeSerializer +import dev.inmo.tgbotapi.CommonAbstracts.WithOptionalLanguageCode import dev.inmo.tgbotapi.types.chat.abstracts.PrivateChat import dev.inmo.tgbotapi.types.chat.extended.ExtendedPrivateChatImpl import dev.inmo.tgbotapi.utils.* @@ -22,8 +25,17 @@ data class CommonUser( @SerialName(usernameField) override val username: Username? = null, @SerialName(languageCodeField) - val languageCode: String? = null -) : User() + @Serializable(IetfLanguageCodeSerializer::class) + override val ietfLanguageCode: IetfLanguageCode? = null +) : User(), WithOptionalLanguageCode { + constructor( + id: UserId, + firstName: String, + lastName: String = "", + username: Username? = null, + languageCode: String + ) : this(id, firstName, lastName, username, IetfLanguageCode(languageCode)) +} @PreviewFeature typealias ExtendedUser = ExtendedPrivateChatImpl diff --git a/tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/types/UserLocale.kt b/tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/types/UserLocale.kt index 33e7b5920b..d2e9da4d08 100644 --- a/tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/types/UserLocale.kt +++ b/tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/types/UserLocale.kt @@ -1,7 +1,8 @@ package dev.inmo.tgbotapi.types +import dev.inmo.micro_utils.language_codes.IetfLanguageCode +import dev.inmo.tgbotapi.CommonAbstracts.WithLanguageCode import java.util.* -fun CommonUser.javaLocale(): Locale? = languageCode ?.let { - Locale.forLanguageTag(it) -} +fun IetfLanguageCode?.javaLocale() = this ?.code ?.let { Locale.forLanguageTag(it) } +fun WithLanguageCode?.javaLocale() = this ?.ietfLanguageCode.javaLocale() diff --git a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/bot/DeleteMyCommands.kt b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/bot/DeleteMyCommands.kt index 31abad88f5..3995e5384a 100644 --- a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/bot/DeleteMyCommands.kt +++ b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/bot/DeleteMyCommands.kt @@ -1,5 +1,6 @@ package dev.inmo.tgbotapi.extensions.api.bot +import dev.inmo.micro_utils.language_codes.IetfLanguageCode import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.requests.bot.DeleteMyCommands import dev.inmo.tgbotapi.types.commands.BotCommandScope @@ -7,5 +8,10 @@ import dev.inmo.tgbotapi.types.commands.BotCommandScopeDefault suspend fun TelegramBot.deleteMyCommands( scope: BotCommandScope = BotCommandScopeDefault, - languageCode: String? = null + languageCode: IetfLanguageCode? ) = execute(DeleteMyCommands(scope, languageCode)) + +suspend fun TelegramBot.deleteMyCommands( + scope: BotCommandScope = BotCommandScopeDefault, + languageCode: String? = null +) = deleteMyCommands(scope, languageCode ?.let(::IetfLanguageCode)) diff --git a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/bot/GetMyCommands.kt b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/bot/GetMyCommands.kt index 07a0c6a3ac..59fb66828d 100644 --- a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/bot/GetMyCommands.kt +++ b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/bot/GetMyCommands.kt @@ -1,5 +1,6 @@ package dev.inmo.tgbotapi.extensions.api.bot +import dev.inmo.micro_utils.language_codes.IetfLanguageCode import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.requests.bot.GetMyCommands import dev.inmo.tgbotapi.types.commands.BotCommandScope @@ -7,5 +8,10 @@ import dev.inmo.tgbotapi.types.commands.BotCommandScopeDefault suspend fun TelegramBot.getMyCommands( scope: BotCommandScope = BotCommandScopeDefault, - languageCode: String? = null + languageCode: IetfLanguageCode? = null ) = execute(GetMyCommands(scope, languageCode)) + +suspend fun TelegramBot.getMyCommands( + scope: BotCommandScope = BotCommandScopeDefault, + languageCode: String? = null +) = getMyCommands(scope, languageCode ?.let(::IetfLanguageCode)) diff --git a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/bot/SetMyCommands.kt b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/bot/SetMyCommands.kt index d0d8b0a8cc..e7f5ef01bc 100644 --- a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/bot/SetMyCommands.kt +++ b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/bot/SetMyCommands.kt @@ -1,5 +1,6 @@ package dev.inmo.tgbotapi.extensions.api.bot +import dev.inmo.micro_utils.language_codes.IetfLanguageCode import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.requests.bot.SetMyCommands import dev.inmo.tgbotapi.types.BotCommand @@ -9,9 +10,21 @@ import dev.inmo.tgbotapi.types.commands.BotCommandScopeDefault suspend fun TelegramBot.setMyCommands( commands: List, scope: BotCommandScope = BotCommandScopeDefault, - languageCode: String? = null + languageCode: IetfLanguageCode? ) = execute(SetMyCommands(commands, scope, languageCode)) +suspend fun TelegramBot.setMyCommands( + vararg commands: BotCommand, + scope: BotCommandScope = BotCommandScopeDefault, + languageCode: IetfLanguageCode? +) = setMyCommands(commands.toList(), scope, languageCode) + +suspend fun TelegramBot.setMyCommands( + commands: List, + scope: BotCommandScope = BotCommandScopeDefault, + languageCode: String? = null +) = setMyCommands(commands, scope, languageCode ?.let(::IetfLanguageCode)) + suspend fun TelegramBot.setMyCommands( vararg commands: BotCommand, scope: BotCommandScope = BotCommandScopeDefault,