diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e59d57fa6..305d25c06c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # TelegramBotAPI changelog +## 20.0.1 + +* `Core`: + * Fix of logger propagation (fix of [#860](https://github.com/InsanusMokrassar/ktgbotapi/issues/860)) + * Add opportunity to modify keyboards (fix of [#761](https://github.com/InsanusMokrassar/ktgbotapi/issues/761)) + * Fields of `OrderInfo` became nullable (fix of [#917](https://github.com/InsanusMokrassar/ktgbotapi/issues/917)) + * Add default `toString` to `ChatType` (fix of [#919](https://github.com/InsanusMokrassar/ktgbotapi/issues/919)) + * Fix of method in `CreateInvoiceLink` (merging of [#920](https://github.com/InsanusMokrassar/ktgbotapi/issues/920), made by [byteduck-exploit](https://github.com/byteduck-exploit)) + ## 20.0.0 **THIS UPDATE CONTAINS SUPPORT OF [BOTS API 7.11](https://core.telegram.org/bots/api-changelog#october-31-2024)** diff --git a/gradle.properties b/gradle.properties index bafc5ec3eb..11147ac396 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,4 +6,4 @@ kotlin.incremental=true kotlin.incremental.js=true library_group=dev.inmo -library_version=20.0.0 +library_version=20.0.1 diff --git a/tgbotapi.core/api/tgbotapi.core.api b/tgbotapi.core/api/tgbotapi.core.api index ecd9912a8a..16aaa02d21 100644 --- a/tgbotapi.core/api/tgbotapi.core.api +++ b/tgbotapi.core/api/tgbotapi.core.api @@ -13558,6 +13558,8 @@ public final class dev/inmo/tgbotapi/types/buttons/InlineKeyboardMarkup : dev/in public fun equals (Ljava/lang/Object;)Z public final fun getKeyboard ()Ljava/util/List; public fun hashCode ()I + public final fun minus (Ldev/inmo/tgbotapi/types/buttons/InlineKeyboardMarkup;)Ldev/inmo/tgbotapi/types/buttons/InlineKeyboardMarkup; + public final fun plus (Ldev/inmo/tgbotapi/types/buttons/InlineKeyboardMarkup;)Ldev/inmo/tgbotapi/types/buttons/InlineKeyboardMarkup; public fun toString ()Ljava/lang/String; } @@ -13872,6 +13874,8 @@ public final class dev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup : dev/inm public static final field Companion Ldev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup$Companion; public fun (Ljava/util/List;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;)V public synthetic fun (Ljava/util/List;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun add (Ldev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup;Ljava/lang/String;)Ldev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup; + public static synthetic fun add$default (Ldev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup;Ldev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup;Ljava/lang/String;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup; public final fun component1 ()Ljava/util/List; public final fun component2 ()Ljava/lang/Boolean; public final fun component3 ()Ljava/lang/Boolean; @@ -13888,6 +13892,8 @@ public final class dev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup : dev/inm public final fun getResizeKeyboard ()Ljava/lang/Boolean; public final fun getSelective ()Ljava/lang/Boolean; public fun hashCode ()I + public final fun minus (Ldev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup;)Ldev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup; + public final fun plus (Ldev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup;)Ldev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup; public fun toString ()Ljava/lang/String; } @@ -14752,6 +14758,7 @@ public final class dev/inmo/tgbotapi/types/chat/ChatSerializersKt { public abstract class dev/inmo/tgbotapi/types/chat/ChatType { public static final field Companion Ldev/inmo/tgbotapi/types/chat/ChatType$Companion; public abstract fun getStringified ()Ljava/lang/String; + public fun toString ()Ljava/lang/String; } public final class dev/inmo/tgbotapi/types/chat/ChatType$Channel : dev/inmo/tgbotapi/types/chat/ChatType { @@ -27066,7 +27073,10 @@ public class dev/inmo/tgbotapi/utils/MatrixBuilder { public fun ()V public final fun add (Ljava/util/List;)Z public final fun getMatrix ()Ljava/util/List; + public final fun modifyRow (ILkotlin/jvm/functions/Function1;)V + public final fun modifyRow (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Z public final fun plus (Ljava/util/List;)Z + public final fun remove (I)Ljava/util/List; public final fun unaryPlus (Ljava/lang/Object;)Z } @@ -27149,6 +27159,9 @@ public class dev/inmo/tgbotapi/utils/RowBuilder { public fun ()V public final fun add (Ljava/lang/Object;)Z public final fun getRow ()Ljava/util/List; + public final fun remove (I)Ljava/lang/Object; + public final fun replace (ILjava/lang/Object;)V + public final fun replace (Ljava/lang/Object;Ljava/lang/Object;)Z public final fun unaryPlus (Ljava/lang/Object;)Z } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutorFactories.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutorFactories.kt index 768d99fcb6..c3623e8e76 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutorFactories.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutorFactories.kt @@ -34,14 +34,14 @@ class KtorRequestsExecutorBuilder( } fun build() = KtorRequestsExecutor( - telegramAPIUrlsKeeper, - client, - callsFactories, - excludeDefaultFactories, - requestsLimiter, - jsonFormatter, - pipelineStepsHolder, - logger + telegramAPIUrlsKeeper = telegramAPIUrlsKeeper, + client = client, + callsFactories = callsFactories, + excludeDefaultFactories = excludeDefaultFactories, + requestsLimiter = requestsLimiter, + jsonFormatter = jsonFormatter, + pipelineStepsHolder = pipelineStepsHolder, + logger = logger ) } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DefaultKtorRequestsExecutor.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DefaultKtorRequestsExecutor.kt index bd29dc2ee6..e08f2c3807 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DefaultKtorRequestsExecutor.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DefaultKtorRequestsExecutor.kt @@ -32,10 +32,10 @@ class DefaultKtorRequestsExecutor internal constructor( ) : BaseRequestsExecutor(telegramAPIUrlsKeeper) { private val callsFactories: List = callsFactories.run { if (!excludeDefaultFactories) { - logger.v { "Installing default factories" } - this + createTelegramBotDefaultKtorCallRequestsFactories(logger) + this@DefaultKtorRequestsExecutor.logger.v { "Installing default factories" } + this + createTelegramBotDefaultKtorCallRequestsFactories(this@DefaultKtorRequestsExecutor.logger) } else { - logger.v { "Default factories will not be installed" } + this@DefaultKtorRequestsExecutor.logger.v { "Default factories will not be installed" } this } } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/payments/CreateInvoiceLink.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/payments/CreateInvoiceLink.kt index 598d9a277b..f1114a47f4 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/payments/CreateInvoiceLink.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/payments/CreateInvoiceLink.kt @@ -54,7 +54,7 @@ data class CreateInvoiceLink( @SerialName(priceDependOnShipAddressField) override val priceDependOnShipAddress: Boolean = false ) : CommonSendInvoiceData, SimpleRequest { - override fun method(): String = "sendInvoice" + override fun method(): String = "createInvoiceLink" override val resultDeserializer: DeserializationStrategy get() = String.serializer() override val requestSerializer: SerializationStrategy<*> diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/InlineKeyboardMarkup.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/InlineKeyboardMarkup.kt index cd17bb80df..6b1e535101 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/InlineKeyboardMarkup.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/InlineKeyboardMarkup.kt @@ -25,4 +25,23 @@ data class InlineKeyboardMarkup( } } } + + operator fun plus(other: InlineKeyboardMarkup): InlineKeyboardMarkup { + return InlineKeyboardMarkup( + keyboard + other.keyboard + ) + } + + operator fun minus(other: InlineKeyboardMarkup): InlineKeyboardMarkup { + val otherButtons = other.keyboard.flatten() + return InlineKeyboardMarkup( + keyboard.mapNotNull { row -> + row.filter { button -> + button !in otherButtons + }.takeIf { + it.isNotEmpty() + } + } + ) + } } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup.kt index 8ffecc9d3f..658792e00f 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/ReplyKeyboardMarkup.kt @@ -22,4 +22,32 @@ data class ReplyKeyboardMarkup( error("Field $inputFieldPlaceholderField length must be in $inputFieldPlaceholderLimit, but was ${inputFieldPlaceholder.length}") } } + + fun add(other: ReplyKeyboardMarkup, placeholderDelimiter: String = "\n"): ReplyKeyboardMarkup { + return ReplyKeyboardMarkup( + keyboard = keyboard + other.keyboard, + resizeKeyboard = resizeKeyboard ?.or(other.resizeKeyboard ?: false) ?: other.resizeKeyboard, + oneTimeKeyboard = oneTimeKeyboard ?.or(other.oneTimeKeyboard ?: false) ?: other.oneTimeKeyboard, + inputFieldPlaceholder = inputFieldPlaceholder ?.plus(other.inputFieldPlaceholder ?.let { placeholderDelimiter + it } ?: "") ?: other.inputFieldPlaceholder, + selective = selective ?.or(other.selective ?: false) ?: other.selective, + persistent = persistent ?.or(other.persistent ?: false) ?: other.persistent, + ) + } + + operator fun plus(other: ReplyKeyboardMarkup): ReplyKeyboardMarkup { + return add(other) + } + + operator fun minus(other: ReplyKeyboardMarkup): ReplyKeyboardMarkup { + val otherButtons = other.keyboard.flatten() + return copy( + keyboard.mapNotNull { row -> + row.filter { button -> + button !in otherButtons + }.takeIf { + it.isNotEmpty() + } + } + ) + } } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ChatSerializers.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ChatSerializers.kt index 0a655096e8..d7f6b23e16 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ChatSerializers.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ChatSerializers.kt @@ -29,6 +29,10 @@ sealed class ChatType { object Channel : ChatType() { override val stringified = "channel" } @Serializable(ChatTypeSerializer::class) class Unknown(override val stringified: String) : ChatType() + + override fun toString(): String { + return stringified + } } val String.asChatType get() = when (this) { diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/payments/OrderInfo.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/payments/OrderInfo.kt index 274449cc45..b7a03d3edb 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/payments/OrderInfo.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/payments/OrderInfo.kt @@ -4,14 +4,21 @@ import dev.inmo.tgbotapi.types.* import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +/** + * All the field of this class are nullable due to specific of [OrderInfo](https://core.telegram.org/bots/api#orderinfo) + * from official bots api + * + * @see dev.inmo.tgbotapi.abstracts.CommonSendInvoiceData + * @see dev.inmo.tgbotapi.requests.send.payments.SendInvoice + */ @Serializable data class OrderInfo( @SerialName(nameField) - val name: String, + val name: String?, @SerialName(phoneNumberField) - val phoneNumber: String, + val phoneNumber: String?, @SerialName(emailField) - val email: String, + val email: String?, @SerialName(shippingAddressField) - val shippingAddress: ShippingAddress + val shippingAddress: ShippingAddress? ) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/Matrix.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/Matrix.kt index c14ae77d0e..7a3a4b56e3 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/Matrix.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/Matrix.kt @@ -1,5 +1,6 @@ package dev.inmo.tgbotapi.utils +import dev.inmo.micro_utils.common.withReplaced import dev.inmo.tgbotapi.types.buttons.Matrix /** @@ -67,6 +68,18 @@ open class RowBuilder { fun add(t: T) = mutRow.add(t) operator fun T.unaryPlus() = add(this) + + fun replace(i: Int, new: T) { + mutRow[i] = new + } + fun replace(old: T, new: T): Boolean { + val i = mutRow.indexOf(old).takeIf { it > -1 } ?: return false + replace(i, new) + return mutRow[i] == new + } + fun remove(i: Int): T { + return mutRow.removeAt(i) + } } open class MatrixBuilder { @@ -77,4 +90,19 @@ open class MatrixBuilder { fun add(t: List) = mutMatrix.add(t) operator fun plus(t: List) = add(t) operator fun T.unaryPlus() = add(listOf(this)) + + fun modifyRow(i: Int, block: RowBuilder.() -> Unit) { + val exists = matrix[i] + val rowBuilder = RowBuilder() + exists.forEach { rowBuilder.add(it) } + mutMatrix[i] = rowBuilder.apply(block).row + } + fun modifyRow(row: List, block: RowBuilder.() -> Unit): Boolean { + val i = mutMatrix.indexOf(row).takeIf { it > -1 } ?: return false + modifyRow(i, block) + return true + } + fun remove(i: Int): List { + return mutMatrix.removeAt(i) + } } diff --git a/tgbotapi.utils/api/tgbotapi.utils.api b/tgbotapi.utils/api/tgbotapi.utils.api index 42b6bfd647..ae493b7ddd 100644 --- a/tgbotapi.utils/api/tgbotapi.utils.api +++ b/tgbotapi.utils/api/tgbotapi.utils.api @@ -3390,6 +3390,7 @@ public final class dev/inmo/tgbotapi/extensions/utils/types/buttons/InlineKeyboa public static synthetic fun inlineQueryInChosenChatButton$default (Ldev/inmo/tgbotapi/utils/RowBuilder;Ljava/lang/String;Ljava/lang/String;ZZZZILjava/lang/Object;)Z public static final fun inlineQueryInCurrentChatButton (Ldev/inmo/tgbotapi/utils/RowBuilder;Ljava/lang/String;Ljava/lang/String;)Z public static final fun loginButton (Ldev/inmo/tgbotapi/utils/RowBuilder;Ljava/lang/String;Ldev/inmo/tgbotapi/types/LoginURL;)Z + public static final fun modified (Ldev/inmo/tgbotapi/types/buttons/InlineKeyboardMarkup;Lkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/types/buttons/InlineKeyboardMarkup; public static final fun payButton (Ldev/inmo/tgbotapi/utils/RowBuilder;Ljava/lang/String;)Z public static final fun urlButton (Ldev/inmo/tgbotapi/utils/RowBuilder;Ljava/lang/String;Ljava/lang/String;)Z public static final fun webAppButton (Ldev/inmo/tgbotapi/utils/RowBuilder;Ljava/lang/String;Ldev/inmo/tgbotapi/types/webapps/WebAppInfo;)Z diff --git a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/types/buttons/InlineKeyboardBuilder.kt b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/types/buttons/InlineKeyboardBuilder.kt index f3a90dee90..152078de6f 100644 --- a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/types/buttons/InlineKeyboardBuilder.kt +++ b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/types/buttons/InlineKeyboardBuilder.kt @@ -49,6 +49,19 @@ inline fun flatInlineKeyboard( block: InlineKeyboardRowBuilder.() -> Unit ) = inlineKeyboard { row(block) } +/** + * Factory-function for [InlineKeyboardBuilder]. It will [apply] [block] to internally created [InlineKeyboardMarkup] + * and [InlineKeyboardBuilder.build] [InlineKeyboardMarkup] then + * + * @see InlineKeyboardBuilder.row + */ +inline fun InlineKeyboardMarkup.modified( + block: InlineKeyboardBuilder.() -> Unit +) = InlineKeyboardBuilder().apply { + keyboard.forEach { add(it) } + block() +}.build() + /** * Creates and put [PayInlineKeyboardButton]