From 3c594537c4fd9b652d9650455aa8d8ee88fadc18 Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 03:20:42 +0300
Subject: [PATCH 01/18] Add chatId parameter to SendGift request

---
 .../pengrad/telegrambot/request/SendGift.kt   | 62 ++++++++++++++++++-
 .../extension/request/SendGiftExtension.kt    | 23 +++++++
 2 files changed, 82 insertions(+), 3 deletions(-)
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/SendGiftExtension.kt

diff --git a/library/src/main/java/com/pengrad/telegrambot/request/SendGift.kt b/library/src/main/java/com/pengrad/telegrambot/request/SendGift.kt
index 0abb5f2f..a98cdeb1 100644
--- a/library/src/main/java/com/pengrad/telegrambot/request/SendGift.kt
+++ b/library/src/main/java/com/pengrad/telegrambot/request/SendGift.kt
@@ -6,12 +6,68 @@ import com.pengrad.telegrambot.response.BaseResponse
 import com.pengrad.telegrambot.utility.kotlin.optionalRequestParameter
 import com.pengrad.telegrambot.utility.kotlin.requestParameter
 
-class SendGift(
-    userId: Long,
+class SendGift private constructor(
+    userId: Long? = null,
+    chatId: Long? = null,
+    channelUsername: String? = null,
     giftId: String,
 ) : KBaseRequest<SendGift, BaseResponse>(BaseResponse::class) {
 
-    val userId: Long by requestParameter(userId)
+    companion object {
+
+        @JvmStatic
+        fun fromUserId(userId: Long, giftId: String) =
+            SendGift(
+                userId = userId,
+                giftId = giftId
+            )
+
+        @JvmSynthetic
+        fun fromChatId(chatId: Long, giftId: String) =
+            SendGift(
+                chatId = chatId,
+                giftId = giftId
+            )
+
+        @JvmStatic
+        fun fromChannel(channelUsername: String, giftId: String) = SendGift(
+            channelUsername = channelUsername,
+            giftId = giftId
+        )
+
+        /**
+         * Backwards compatability to constructor with userId
+         */
+        @Deprecated("Use constructor(chatId, giftId) instead", ReplaceWith("SendGift(userId, giftId)"))
+        operator fun invoke(userId: Long, giftId: String) =
+            fromUserId(
+                userId = userId,
+                giftId = giftId
+            )
+
+    }
+
+    constructor(chatId: Long, giftId: String) : this(
+        userId = null,
+        chatId = chatId,
+        channelUsername = null,
+        giftId = giftId
+    )
+
+    constructor(
+        channelUsername: String,
+        giftId: String
+    ) : this(
+        userId = null,
+        chatId = null,
+        channelUsername = channelUsername,
+        giftId = giftId
+    )
+
+    val userId: Long? by optionalRequestParameter(userId)
+    val chatId: Long? by optionalRequestParameter(chatId, customParameterName = "chat_id")
+    val channelUsername: String? by optionalRequestParameter(channelUsername, customParameterName = "chat_id")
+
     val giftId: String by requestParameter(giftId)
 
     var text: String? by optionalRequestParameter()
diff --git a/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/SendGiftExtension.kt b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/SendGiftExtension.kt
new file mode 100644
index 00000000..ac4e1126
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/SendGiftExtension.kt
@@ -0,0 +1,23 @@
+package com.pengrad.telegrambot.utility.kotlin.extension.request
+
+import com.pengrad.telegrambot.TelegramAware
+import com.pengrad.telegrambot.request.SendGift
+import com.pengrad.telegrambot.utility.kotlin.extension.execute
+
+inline fun TelegramAware.sendGift(
+    chatId: Long,
+    giftId: String,
+    modifier: SendGift.() -> Unit = {}
+) = this.execute(SendGift(
+    chatId = chatId,
+    giftId = giftId
+), modifier)
+
+inline fun TelegramAware.sendGift(
+    channelUsername: String,
+    giftId: String,
+    modifier: SendGift.() -> Unit = {}
+) = this.execute(SendGift(
+    channelUsername = channelUsername,
+    giftId = giftId
+), modifier)
\ No newline at end of file

From 583824321fd5cb8b2d85d9f1ac265719785548bd Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 03:21:58 +0300
Subject: [PATCH 02/18] Add can_send_gift field to ChatFullInfo

---
 .../java/com/pengrad/telegrambot/model/ChatFullInfo.java | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/library/src/main/java/com/pengrad/telegrambot/model/ChatFullInfo.java b/library/src/main/java/com/pengrad/telegrambot/model/ChatFullInfo.java
index 6ddec3e5..8e7b96cb 100644
--- a/library/src/main/java/com/pengrad/telegrambot/model/ChatFullInfo.java
+++ b/library/src/main/java/com/pengrad/telegrambot/model/ChatFullInfo.java
@@ -70,6 +70,7 @@ public enum Type {
     private String custom_emoji_sticker_set_name;
     private Long linked_chat_id;
     private ChatLocation location;
+    private Boolean can_send_gift;
 
     public Long id() {
         return id;
@@ -262,6 +263,10 @@ public ChatLocation location() {
         return location;
     }
 
+    public Boolean canSendGift() {
+        return can_send_gift;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
@@ -310,7 +315,8 @@ public boolean equals(Object o) {
                 Objects.equals(can_set_sticker_set, chat.can_set_sticker_set) &&
                 Objects.equals(custom_emoji_sticker_set_name, chat.custom_emoji_sticker_set_name) &&
                 Objects.equals(linked_chat_id, chat.linked_chat_id) &&
-                Objects.equals(location, chat.location);
+                Objects.equals(location, chat.location) &&
+                Objects.equals(can_send_gift, chat.can_send_gift);
     }
 
     @Override
@@ -365,6 +371,7 @@ public String toString() {
                 ", custom_emoji_sticker_set_name=" + custom_emoji_sticker_set_name +
                 ", linked_chat_id=" + linked_chat_id +
                 ", location=" + location +
+                ", can_send_gift=" + can_send_gift +
                 '}';
     }
 }

From 65f0c1faebad474dd53f5f30063f95a39c7dcd70 Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 03:25:55 +0300
Subject: [PATCH 03/18] Add TransactionPartnerChat transaction partner

---
 .../stars/partner/TransactionPartnerChat.kt   | 39 +++++++++++++++++++
 .../stars/partner/TransactionPartnerType.kt   |  1 +
 .../gson/TransactionPartnerTypeAdapter.kt     |  2 +
 3 files changed, 42 insertions(+)
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/model/stars/partner/TransactionPartnerChat.kt

diff --git a/library/src/main/java/com/pengrad/telegrambot/model/stars/partner/TransactionPartnerChat.kt b/library/src/main/java/com/pengrad/telegrambot/model/stars/partner/TransactionPartnerChat.kt
new file mode 100644
index 00000000..d3758ce5
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/model/stars/partner/TransactionPartnerChat.kt
@@ -0,0 +1,39 @@
+package com.pengrad.telegrambot.model.stars.partner
+
+import com.pengrad.telegrambot.model.Chat
+import com.pengrad.telegrambot.model.User
+import com.pengrad.telegrambot.model.gift.Gift
+import com.pengrad.telegrambot.model.paidmedia.PaidMedia
+import com.pengrad.telegrambot.model.stars.affiliate.AffiliateInfo
+import com.pengrad.telegrambot.model.stars.partner.TransactionPartnerType.CHAT
+import com.pengrad.telegrambot.model.stars.partner.TransactionPartnerType.USER
+
+data class TransactionPartnerChat(
+    @get:JvmName("chat") val chat: Chat,
+    @get:JvmName("gift") val gift: Gift? = null
+) : TransactionPartner {
+
+    override val type: String
+        get() = CHAT
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (javaClass != other?.javaClass) return false
+
+        other as TransactionPartnerChat
+
+        if (chat != other.chat) return false
+        if (gift != other.gift) return false
+        if (type != other.type) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = chat.hashCode()
+        result = 31 * result + (gift?.hashCode() ?: 0)
+        return result
+    }
+
+
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/pengrad/telegrambot/model/stars/partner/TransactionPartnerType.kt b/library/src/main/java/com/pengrad/telegrambot/model/stars/partner/TransactionPartnerType.kt
index b3922be1..fcb7cb3d 100644
--- a/library/src/main/java/com/pengrad/telegrambot/model/stars/partner/TransactionPartnerType.kt
+++ b/library/src/main/java/com/pengrad/telegrambot/model/stars/partner/TransactionPartnerType.kt
@@ -3,6 +3,7 @@ package com.pengrad.telegrambot.model.stars.partner
 object TransactionPartnerType {
 
     const val USER = "user"
+    const val CHAT = "chat"
     const val AFFILIATE_PROGRAM = "affiliate_program"
     const val FRAGMENT = "fragment"
     const val TELEGRAM_ADS = "telegram_ads"
diff --git a/library/src/main/java/com/pengrad/telegrambot/utility/gson/TransactionPartnerTypeAdapter.kt b/library/src/main/java/com/pengrad/telegrambot/utility/gson/TransactionPartnerTypeAdapter.kt
index e7aa219b..b7487798 100644
--- a/library/src/main/java/com/pengrad/telegrambot/utility/gson/TransactionPartnerTypeAdapter.kt
+++ b/library/src/main/java/com/pengrad/telegrambot/utility/gson/TransactionPartnerTypeAdapter.kt
@@ -3,6 +3,7 @@ package com.pengrad.telegrambot.utility.gson
 import com.google.gson.*
 import com.pengrad.telegrambot.model.stars.partner.*
 import com.pengrad.telegrambot.model.stars.partner.TransactionPartnerType.AFFILIATE_PROGRAM
+import com.pengrad.telegrambot.model.stars.partner.TransactionPartnerType.CHAT
 import com.pengrad.telegrambot.model.stars.partner.TransactionPartnerType.FRAGMENT
 import com.pengrad.telegrambot.model.stars.partner.TransactionPartnerType.OTHER
 import com.pengrad.telegrambot.model.stars.partner.TransactionPartnerType.TELEGRAM_ADS
@@ -15,6 +16,7 @@ object TransactionPartnerTypeAdapter : JsonDeserializer<TransactionPartner> {
 
     private val typeMapping = mapOf(
         USER to TransactionPartnerUser::class,
+        CHAT to TransactionPartnerChat::class,
         AFFILIATE_PROGRAM to TransactionPartnerAffiliateProgram::class,
         FRAGMENT to TransactionPartnerFragment::class,
         TELEGRAM_ADS to TransactionPartnerTelegramAds::class,

From dfc51f0b3cac827ac646fac3ea4548af6f02907a Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 03:37:54 +0300
Subject: [PATCH 04/18] Add cover and start_timestamp fields to Video and
 rewrite it to Kotlin

---
 .../com/pengrad/telegrambot/model/Video.java  | 103 ------------------
 .../com/pengrad/telegrambot/model/Video.kt    |  43 ++++++++
 2 files changed, 43 insertions(+), 103 deletions(-)
 delete mode 100644 library/src/main/java/com/pengrad/telegrambot/model/Video.java
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/model/Video.kt

diff --git a/library/src/main/java/com/pengrad/telegrambot/model/Video.java b/library/src/main/java/com/pengrad/telegrambot/model/Video.java
deleted file mode 100644
index 2fead3fc..00000000
--- a/library/src/main/java/com/pengrad/telegrambot/model/Video.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package com.pengrad.telegrambot.model;
-
-import java.io.Serializable;
-import java.util.Objects;
-
-/**
- * stas
- * 8/5/15.
- */
-public class Video implements Serializable {
-    private final static long serialVersionUID = 0L;
-
-    private String file_id;
-    private String file_unique_id;
-    private Integer width;
-    private Integer height;
-    private Integer duration;
-    private PhotoSize thumbnail;
-  
-    private String file_name;
-    private String mime_type;
-    private Long file_size;
-
-    public String fileId() {
-        return file_id;
-    }
-
-    public String fileUniqueId() {
-        return file_unique_id;
-    }
-
-    public Integer width() {
-        return width;
-    }
-
-    public Integer height() {
-        return height;
-    }
-
-    public Integer duration() {
-        return duration;
-    }
-
-    public PhotoSize thumbnail() {
-        return thumbnail;
-    }
-
-    /**
-     * @deprecated Use thumbnail instead
-     */
-    @Deprecated 
-    public PhotoSize thumb() {
-        return thumbnail();
-    }
-
-    public String fileName() {
-        return file_name;
-    }
-
-    public String mimeType() {
-        return mime_type;
-    }
-
-    public Long fileSize() {
-        return file_size;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        Video video = (Video) o;
-        return Objects.equals(file_id, video.file_id) &&
-                Objects.equals(file_unique_id, video.file_unique_id) &&
-                Objects.equals(width, video.width) &&
-                Objects.equals(height, video.height) &&
-                Objects.equals(duration, video.duration) &&
-                Objects.equals(thumbnail, video.thumbnail) &&
-                Objects.equals(file_name, video.file_name) &&
-                Objects.equals(mime_type, video.mime_type) &&
-                Objects.equals(file_size, video.file_size);
-    }
-
-    @Override
-    public int hashCode() {
-        return file_id != null ? file_id.hashCode() : 0;
-    }
-
-    @Override
-    public String toString() {
-        return "Video{" +
-                "file_id='" + file_id + '\'' +
-                ", file_unique_id='" + file_unique_id + '\'' +
-                ", width=" + width +
-                ", height=" + height +
-                ", duration=" + duration +
-                ", thumbnail=" + thumbnail +
-                ", file_name='" + file_name + '\'' +
-                ", mime_type='" + mime_type + '\'' +
-                ", file_size=" + file_size +
-                '}';
-    }
-}
diff --git a/library/src/main/java/com/pengrad/telegrambot/model/Video.kt b/library/src/main/java/com/pengrad/telegrambot/model/Video.kt
new file mode 100644
index 00000000..615fade4
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/model/Video.kt
@@ -0,0 +1,43 @@
+package com.pengrad.telegrambot.model
+
+data class Video(
+    @get:JvmName("fileId") val fileId: String,
+    @get:JvmName("fileUniqueId") val fileUniqueId: String,
+
+    @JvmSynthetic val width: Int,
+    @JvmSynthetic val height: Int,
+    @JvmSynthetic val duration: Int,
+
+    @get:JvmName("thumbnail") val thumbnail: PhotoSize? = null,
+    @get:JvmName("cover") val cover: List<PhotoSize>? = null,
+
+    @get:JvmName("start_timestamp") val startTimestamp: Int? = null,
+
+    @get:JvmName("fileName") val fileName: String? = null,
+    @get:JvmName("mimeType") val mimeType: String? = null,
+    @get:JvmName("fileSize") val fileSize: Long? = null,
+
+) {
+
+    /**
+     * Backwards compatability for Java code because of Kotlin optimization
+     */
+    @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
+    fun width() = width as Integer
+
+    /**
+     * Backwards compatability for Java code because of Kotlin optimization
+     */
+    @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
+    fun height() = height as Integer
+
+    /**
+     * Backwards compatability for Java code because of Kotlin optimization
+     */
+    @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
+    fun duration() = duration as Integer
+
+    @Deprecated("Use thumbnail instead", ReplaceWith("thumbnail"))
+    fun thumb(): PhotoSize? = thumbnail
+
+}
\ No newline at end of file

From 8a5dd718a6ee2196a00e6b64ec7e000c335465d3 Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 04:48:36 +0300
Subject: [PATCH 05/18] Add cover and start_timestamp fields to SendVideo
 request and rewrite it to Kotlin

---
 .../request/KAbstractMultipartRequest.kt      |  59 +++++++
 .../request/KAbstractSendRequest.kt           |  65 ++++++++
 .../telegrambot/request/KBaseRequest.kt       |   6 +
 .../telegrambot/request/SendVideo.java        | 100 ------------
 .../pengrad/telegrambot/request/SendVideo.kt  | 147 ++++++++++++++++++
 5 files changed, 277 insertions(+), 100 deletions(-)
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/request/KAbstractMultipartRequest.kt
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/request/KAbstractSendRequest.kt
 delete mode 100644 library/src/main/java/com/pengrad/telegrambot/request/SendVideo.java
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/request/SendVideo.kt

diff --git a/library/src/main/java/com/pengrad/telegrambot/request/KAbstractMultipartRequest.kt b/library/src/main/java/com/pengrad/telegrambot/request/KAbstractMultipartRequest.kt
new file mode 100644
index 00000000..8c6c124b
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/request/KAbstractMultipartRequest.kt
@@ -0,0 +1,59 @@
+package com.pengrad.telegrambot.request
+
+import com.pengrad.telegrambot.utility.kotlin.optionalRequestParameter
+import java.io.File
+
+abstract class KAbstractMultipartRequest<REQ : KAbstractMultipartRequest<REQ>>(
+    chatId: Long?,
+    channelUsername: String?,
+
+    contentParameterName: String,
+    contentUrl: String?,
+    contentFile: File?,
+    contentBytes: ByteArray?,
+
+    defaultFileName: String,
+    defaultContentType: String
+) : KAbstractSendRequest<REQ>(
+    chatId = chatId,
+    channelUsername = channelUsername
+) {
+
+    val contentUrl by optionalRequestParameter(contentUrl, customParameterName = contentParameterName)
+    val contentFile by optionalRequestParameter(contentFile, customParameterName = contentParameterName)
+    val contentBytes by optionalRequestParameter(contentBytes, customParameterName = contentParameterName)
+
+    var thumbnailFile: File? by optionalRequestParameter(customParameterName = "thumbnail")
+    var thumbnailBytes: ByteArray? by optionalRequestParameter(customParameterName = "thumbnail")
+
+    @get:JvmName("isUseMultipart")
+    val isMultipart: Boolean
+        get() = contentFile != null || contentBytes != null
+                || thumbnailFile != null || thumbnailBytes != null
+
+    @get:JvmName("getContentFileName")
+    var fileName: String = contentFile?.name ?: defaultFileName
+    @get:JvmName("getContentMimeType")
+    var contentType: String = defaultContentType
+
+    fun thumbnail(thumbnail: File) = applySelf { this.thumbnailFile = thumbnail }
+
+    fun thumbnail(thumbnail: ByteArray) = applySelf { this.thumbnailBytes = thumbnail }
+
+    @Deprecated("Use thumbnail instead", ReplaceWith("thumbnail(thumbnail)"))
+    fun thumb(thumbnail: File) = applySelf { this.thumbnailFile = thumbnail }
+
+    @Deprecated("Use thumbnail instead", ReplaceWith("thumbnail(thumbnail)"))
+    fun thumb(thumbnail: ByteArray) = applySelf { this.thumbnailBytes = thumbnail }
+
+    fun fileName(fileName: String) = applySelf { this.fileName = fileName }
+
+    fun contentType(contentType: String) = applySelf { this.contentType = contentType }
+
+    override fun isMultipart() = isMultipart
+
+    override fun getFileName() = fileName
+
+    override fun getContentType() = contentType
+
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/pengrad/telegrambot/request/KAbstractSendRequest.kt b/library/src/main/java/com/pengrad/telegrambot/request/KAbstractSendRequest.kt
new file mode 100644
index 00000000..ae11d8fa
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/request/KAbstractSendRequest.kt
@@ -0,0 +1,65 @@
+package com.pengrad.telegrambot.request
+
+import com.pengrad.telegrambot.model.request.Keyboard
+import com.pengrad.telegrambot.model.request.ReplyParameters
+import com.pengrad.telegrambot.response.SendResponse
+import com.pengrad.telegrambot.utility.kotlin.optionalRequestParameter
+
+abstract class KAbstractSendRequest<REQ : KAbstractSendRequest<REQ>>(
+    chatId: Long?,
+    channelUsername: String?
+) : KBaseRequest<REQ, SendResponse>(SendResponse::class) {
+
+    val chatId: Long? by optionalRequestParameter(chatId, customParameterName = "chat_id")
+    val channelUsername: String? by optionalRequestParameter(channelUsername, customParameterName = "chat_id")
+
+    var businessConnectionId: String? by optionalRequestParameter()
+    var messageThreadId: Int? by optionalRequestParameter()
+    var disableNotification: Boolean? by optionalRequestParameter()
+    var protectContent: Boolean? by optionalRequestParameter()
+    var allowPaidBroadcast: Boolean? by optionalRequestParameter()
+    var messageEffectId: String? by optionalRequestParameter()
+    var replyParameters: ReplyParameters? by optionalRequestParameter()
+    @Deprecated("Use replyParameters instead")
+    private var replyToMessageId: Int? by optionalRequestParameter()
+    @Deprecated("Use replyParameters instead")
+    private var allowSendingWithoutReply: Boolean? by optionalRequestParameter()
+    var replyMarkup: Keyboard? by optionalRequestParameter()
+
+    fun businessConnectionId(businessConnectionId: String) = applySelf { this.businessConnectionId = businessConnectionId }
+
+    fun messageThreadId(messageThreadId: Int) = applySelf { this.messageThreadId = messageThreadId }
+
+    fun disableNotification(disableNotification: Boolean) = applySelf { this.disableNotification = disableNotification }
+
+    fun protectContent(protectContent: Boolean) = applySelf { this.protectContent = protectContent }
+
+    fun allowPaidBroadcast(allowPaidBroadcast: Boolean) = applySelf { this.allowPaidBroadcast = allowPaidBroadcast }
+
+    fun messageEffectId(messageEffectId: String) = applySelf { this.messageEffectId = messageEffectId }
+
+    fun replyParameters(replyParameters: ReplyParameters) = applySelf { this.replyParameters = replyParameters }
+
+    @Suppress("DEPRECATION")
+    @Deprecated(
+        message = "Use replyParameters instead",
+        ReplaceWith(
+            expression = "replyParameters(ReplyParameters(replyToMessageId))",
+            imports = ["com.pengrad.telegrambot.model.request.ReplyParameters"]
+        )
+    )
+    fun replyToMessageId(replyToMessageId: Int) = applySelf { this.replyToMessageId = replyToMessageId }
+
+    @Suppress("DEPRECATION")
+    @Deprecated(
+        message = "Use replyParameters instead",
+        ReplaceWith(
+            expression = "replyParameters(ReplyParameters(messageId).allowSendingWithoutReply(allowSendingWithoutReply))",
+            imports = ["com.pengrad.telegrambot.model.request.ReplyParameters"]
+        )
+    )
+    fun allowSendingWithoutReply(allowSendingWithoutReply: Boolean) = applySelf { this.allowSendingWithoutReply = allowSendingWithoutReply }
+
+    fun replyMarkup(replyMarkup: Keyboard) = applySelf { this.replyMarkup = replyMarkup }
+
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/pengrad/telegrambot/request/KBaseRequest.kt b/library/src/main/java/com/pengrad/telegrambot/request/KBaseRequest.kt
index c732d542..3a5b28f6 100644
--- a/library/src/main/java/com/pengrad/telegrambot/request/KBaseRequest.kt
+++ b/library/src/main/java/com/pengrad/telegrambot/request/KBaseRequest.kt
@@ -7,8 +7,14 @@ abstract class KBaseRequest<T : BaseRequest<T, R>, R : BaseResponse>(
     clazz: KClass<R>
 ) : BaseRequest<T, R>(clazz.java) {
 
+    @Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate")
+    protected val self by lazy { this as T }
+
     internal fun addParameter(name: String, value: Any?): T {
         return add(name, value)
     }
 
+    protected fun applySelf(block: T.() -> Unit): T =
+        self.apply(block)
+
 }
\ No newline at end of file
diff --git a/library/src/main/java/com/pengrad/telegrambot/request/SendVideo.java b/library/src/main/java/com/pengrad/telegrambot/request/SendVideo.java
deleted file mode 100644
index 8c4bfae5..00000000
--- a/library/src/main/java/com/pengrad/telegrambot/request/SendVideo.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.pengrad.telegrambot.request;
-
-import com.pengrad.telegrambot.model.MessageEntity;
-import com.pengrad.telegrambot.model.request.ParseMode;
-
-import java.io.File;
-
-/**
- * stas
- * 5/1/16.
- */
-public class SendVideo extends AbstractMultipartRequest<SendVideo> {
-
-    public SendVideo(Object chatId, String video) {
-        super(chatId, video);
-    }
-
-    public SendVideo(Object chatId, File video) {
-        super(chatId, video);
-    }
-
-    public SendVideo(Object chatId, byte[] video) {
-        super(chatId, video);
-    }
-
-    public SendVideo duration(int duration) {
-        return add("duration", duration);
-    }
-
-    public SendVideo width(int width) {
-        return add("width", width);
-    }
-
-    public SendVideo height(int height) {
-        return add("height", height);
-    }
-
-    /**
-     * @deprecated Use thumbnail instead
-     */
-    @Deprecated
-    public SendVideo thumb(byte[] thumb) {
-        return thumbnail(thumb);
-    }
-
-    /**
-     * @deprecated Use thumbnail instead
-     */
-    @Deprecated
-    public SendVideo thumb(File thumb) {
-        return thumbnail(thumb);
-    }
-
-    public SendVideo thumbnail(byte[] thumbnail) {
-        return super.thumbnail(thumbnail);
-    }
-
-    public SendVideo thumbnail(File thumbnail) {
-        return super.thumbnail(thumbnail);
-    }
-
-    public SendVideo caption(String caption) {
-        return add("caption", caption);
-    }
-
-    public SendVideo parseMode(ParseMode parseMode) {
-        return add("parse_mode", parseMode.name());
-    }
-
-    public SendVideo captionEntities(MessageEntity... entities) {
-        return add("caption_entities", entities);
-    }
-
-    public SendVideo supportsStreaming(boolean supportsStreaming) {
-        return add("supports_streaming", supportsStreaming);
-    }
-
-    public SendVideo hasSpoiler(boolean has_spoiler) {
-        return add("has_spoiler", has_spoiler);
-    }
-
-    public SendVideo showCaptionAboveMedia(Boolean showCaptionAboveMedia) {
-        return add("show_caption_above_media", showCaptionAboveMedia);
-    }
-
-    @Override
-    protected String getFileParamName() {
-        return "video";
-    }
-
-    @Override
-    public String getDefaultFileName() {
-        return ContentTypes.VIDEO_FILE_NAME;
-    }
-
-    @Override
-    public String getDefaultContentType() {
-        return ContentTypes.VIDEO_MIME_TYPE;
-    }
-}
diff --git a/library/src/main/java/com/pengrad/telegrambot/request/SendVideo.kt b/library/src/main/java/com/pengrad/telegrambot/request/SendVideo.kt
new file mode 100644
index 00000000..d29499a0
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/request/SendVideo.kt
@@ -0,0 +1,147 @@
+package com.pengrad.telegrambot.request
+
+import com.pengrad.telegrambot.model.MessageEntity
+import com.pengrad.telegrambot.model.request.ParseMode
+import com.pengrad.telegrambot.utility.kotlin.optionalRequestParameter
+import java.io.File
+
+class SendVideo private constructor(
+    chatId: Long? = null,
+    channelUsername: String? = null,
+
+    videoUrl: String? = null,
+    videoFile: File? = null,
+    videoBytes: ByteArray? = null
+) : KAbstractMultipartRequest<SendVideo>(
+    chatId = chatId,
+    channelUsername = channelUsername,
+
+    contentParameterName = "video",
+    contentUrl = videoUrl,
+    contentFile = videoFile,
+    contentBytes = videoBytes,
+
+    defaultFileName = ContentTypes.VIDEO_FILE_NAME,
+    defaultContentType = ContentTypes.VIDEO_MIME_TYPE
+) {
+
+    constructor(chatId: Long, videoUrl: String) : this(
+        chatId = chatId,
+        channelUsername = null,
+        videoUrl = videoUrl
+    )
+
+    constructor(channelUsername: String, videoUrl: String) : this(
+        chatId = null,
+        channelUsername = channelUsername,
+        videoUrl = videoUrl
+    )
+
+
+    constructor(chatId: Long, videoFile: File) : this(
+        chatId = chatId,
+        channelUsername = null,
+        videoFile = videoFile
+    )
+
+    constructor(channelUsername: String, videoFile: File) : this(
+        chatId = null,
+        channelUsername = channelUsername,
+        videoFile = videoFile
+    )
+
+
+    constructor(chatId: Long, videoBytes: ByteArray) : this(
+        chatId = chatId,
+        channelUsername = null,
+        videoBytes = videoBytes
+    )
+
+    constructor(channelUsername: String, videoBytes: ByteArray) : this(
+        chatId = null,
+        channelUsername = channelUsername,
+        videoBytes = videoBytes
+    )
+
+
+    @Deprecated("Use constructor with chatId or channelUsername instead", ReplaceWith("SendVideo(chatId, video)"))
+    constructor(chatId: Any, video: String) : this(
+        chatId = (chatId as? Number)?.toLong(),
+        channelUsername = chatId as? String,
+        videoUrl = video
+    ) {
+        checkDeprecatedConstructorParameters()
+    }
+
+    @Deprecated("Use constructor with chatId or channelUsername instead", ReplaceWith("SendVideo(chatId, video)"))
+    constructor(chatId: Any, video: File) : this(
+        chatId = (chatId as? Number)?.toLong(),
+        channelUsername = chatId as? String,
+        videoFile = video
+    ) {
+        checkDeprecatedConstructorParameters()
+    }
+
+    @Deprecated("Use constructor with chatId or channelUsername instead", ReplaceWith("SendVideo(chatId, video)"))
+    constructor(chatId: Any, video: ByteArray) : this(
+        chatId = (chatId as? Number)?.toLong(),
+        channelUsername = chatId as? String,
+        videoBytes = video
+    ) {
+        checkDeprecatedConstructorParameters()
+    }
+
+    @Suppress("NOTHING_TO_INLINE")
+    private inline fun checkDeprecatedConstructorParameters() {
+        if (this.chatId == null && this.channelUsername == null) {
+            throw IllegalArgumentException("chatId parameter must be either Long or String")
+        }
+    }
+
+    var duration: Int? by optionalRequestParameter()
+    var width: Int? by optionalRequestParameter()
+    var height: Int? by optionalRequestParameter()
+
+    var coverUrl: String? by optionalRequestParameter(customParameterName = "cover")
+    var coverFile: File? by optionalRequestParameter(customParameterName = "cover")
+    var coverBytes: ByteArray? by optionalRequestParameter(customParameterName = "cover")
+
+    var startTimestamp: Int? by optionalRequestParameter()
+
+    var caption: String? by optionalRequestParameter()
+    var parseMode: ParseMode? by optionalRequestParameter()
+    var captionEntities: List<MessageEntity>? by optionalRequestParameter()
+    var showCaptionAboveMedia: Boolean? by optionalRequestParameter()
+
+    var hasSpoiler: Boolean? by optionalRequestParameter()
+    var supportsStreaming: Boolean? by optionalRequestParameter()
+
+    fun duration(duration: Int) = applySelf { this.duration = duration }
+
+    fun width(width: Int) = applySelf { this.width = width }
+
+    fun height(height: Int) = applySelf { this.height = height }
+
+    fun coverUrl(coverUrl: String) = applySelf { this.coverUrl = coverUrl }
+
+    fun coverFile(coverFile: File) = applySelf { this.coverFile = coverFile }
+
+    fun coverBytes(coverBytes: ByteArray) = applySelf { this.coverBytes = coverBytes }
+
+    fun startTimestamp(startTimestamp: Int) = applySelf { this.startTimestamp = startTimestamp }
+
+    fun caption(caption: String) = applySelf { this.caption = caption }
+
+    fun parseMode(parseMode: ParseMode) = applySelf { this.parseMode = parseMode }
+
+    fun captionEntities(captionEntities: List<MessageEntity>) = applySelf { this.captionEntities = captionEntities }
+
+    fun captionEntities(vararg captionEntities: MessageEntity) = applySelf { this.captionEntities = captionEntities.toList() }
+
+    fun showCaptionAboveMedia(showCaptionAboveMedia: Boolean) = applySelf { this.showCaptionAboveMedia = showCaptionAboveMedia }
+
+    fun hasSpoiler(hasSpoiler: Boolean) = applySelf { this.hasSpoiler = hasSpoiler }
+
+    fun supportsStreaming(supportsStreaming: Boolean) = applySelf { this.supportsStreaming = supportsStreaming }
+
+}
\ No newline at end of file

From 54dc6dde832cb48978bb3f9ac9bc36ac199e3423 Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 05:48:53 +0300
Subject: [PATCH 06/18] Add cover and start_timestamp parameters to
 InputMediaVideo and InputPaidMediaVideo

---
 .../telegrambot/model/request/InputMedia.java | 22 +++++++--------
 .../model/request/InputMediaVideo.java        | 17 ++++++++++++
 .../model/request/InputPaidMedia.java         |  6 +++++
 .../model/request/InputPaidMediaVideo.java    | 27 +++++++++++++------
 4 files changed, 52 insertions(+), 20 deletions(-)

diff --git a/library/src/main/java/com/pengrad/telegrambot/model/request/InputMedia.java b/library/src/main/java/com/pengrad/telegrambot/model/request/InputMedia.java
index a6e00ed8..11edb6ca 100644
--- a/library/src/main/java/com/pengrad/telegrambot/model/request/InputMedia.java
+++ b/library/src/main/java/com/pengrad/telegrambot/model/request/InputMedia.java
@@ -54,6 +54,12 @@ public Map<String, Object> getAttachments() {
         return attachments;
     }
 
+    protected String addAttachment(Object attachment) {
+        String attachName = AttachName.next();
+        attachments.put(attachName, attachment);
+        return "attach://" + attachName;
+    }
+
     public InputFile inputFile() {
         return inputFile;
     }
@@ -67,9 +73,7 @@ public String getInputFileId() {
      */
     @Deprecated
     public T thumb(File thumb) {
-        String attachName = AttachName.next();
-        attachments.put(attachName, thumb);
-        this.thumbnail = "attach://" + attachName;
+        this.thumbnail = addAttachment(thumb);
         return thisAsT;
     }
 
@@ -83,23 +87,17 @@ public T showCaptionAboveMedia(Boolean showCaptionAboveMedia) {
      */
     @Deprecated
     public T thumb(byte[] thumb) {
-        String attachName = AttachName.next();
-        attachments.put(attachName, thumb);
-        this.thumbnail = "attach://" + attachName;
+        this.thumbnail = addAttachment(thumb);
         return thisAsT;
     }
 
     public T thumbnail(File thumbnail) {
-        String attachName = AttachName.next();
-        attachments.put(attachName, thumbnail);
-        this.thumbnail = "attach://" + attachName;
+        this.thumbnail = addAttachment(thumbnail);
         return thisAsT;
     }
 
     public T thumbnail(byte[] thumbnail) {
-        String attachName = AttachName.next();
-        attachments.put(attachName, thumbnail);
-        this.thumbnail = "attach://" + attachName;
+        this.thumbnail = addAttachment(thumbnail);
         return thisAsT;
     }
 
diff --git a/library/src/main/java/com/pengrad/telegrambot/model/request/InputMediaVideo.java b/library/src/main/java/com/pengrad/telegrambot/model/request/InputMediaVideo.java
index 9e52b996..ff8ef964 100644
--- a/library/src/main/java/com/pengrad/telegrambot/model/request/InputMediaVideo.java
+++ b/library/src/main/java/com/pengrad/telegrambot/model/request/InputMediaVideo.java
@@ -15,6 +15,8 @@ public class InputMediaVideo extends InputMedia<InputMediaVideo> implements Seri
     private Integer width, height, duration;
     private Boolean supports_streaming;
     private Boolean has_spoiler;
+    private String cover;
+    private Integer start_timestamp;
 
     public InputMediaVideo(String media) {
         super("video", media);
@@ -43,6 +45,21 @@ public InputMediaVideo duration(Integer duration) {
         return this;
     }
 
+    public InputMediaVideo cover(File cover) {
+        this.cover = addAttachment(cover);
+        return this;
+    }
+
+    public InputMediaVideo cover(byte[] cover) {
+        this.cover = addAttachment(cover);
+        return this;
+    }
+
+    public InputMediaVideo startTimestamp(Integer startTimestamp) {
+        this.start_timestamp = startTimestamp;
+        return this;
+    }
+
     public InputMediaVideo supportsStreaming(boolean supportsStreaming) {
         this.supports_streaming = supportsStreaming;
         return this;
diff --git a/library/src/main/java/com/pengrad/telegrambot/model/request/InputPaidMedia.java b/library/src/main/java/com/pengrad/telegrambot/model/request/InputPaidMedia.java
index 3237b198..42b64a28 100644
--- a/library/src/main/java/com/pengrad/telegrambot/model/request/InputPaidMedia.java
+++ b/library/src/main/java/com/pengrad/telegrambot/model/request/InputPaidMedia.java
@@ -39,6 +39,12 @@ public Map<String, Object> getAttachments() {
         return attachments;
     }
 
+    protected String addAttachment(Object attachment) {
+        String attachName = AttachName.next();
+        attachments.put(attachName, attachment);
+        return "attach://" + attachName;
+    }
+
     public InputFile inputFile() {
         return inputFile;
     }
diff --git a/library/src/main/java/com/pengrad/telegrambot/model/request/InputPaidMediaVideo.java b/library/src/main/java/com/pengrad/telegrambot/model/request/InputPaidMediaVideo.java
index 4c1e7509..59adc956 100644
--- a/library/src/main/java/com/pengrad/telegrambot/model/request/InputPaidMediaVideo.java
+++ b/library/src/main/java/com/pengrad/telegrambot/model/request/InputPaidMediaVideo.java
@@ -1,11 +1,9 @@
 package com.pengrad.telegrambot.model.request;
 
-import com.pengrad.telegrambot.AttachName;
 import com.pengrad.telegrambot.request.ContentTypes;
 
 import java.io.File;
 import java.io.Serializable;
-import java.util.Map;
 
 public class InputPaidMediaVideo extends InputPaidMedia implements Serializable {
 
@@ -14,6 +12,8 @@ public class InputPaidMediaVideo extends InputPaidMedia implements Serializable
     private Integer width, height, duration;
     private Boolean supports_streaming;
     private String thumbnail;
+    private String cover;
+    private Integer start_timestamp;
 
     public InputPaidMediaVideo(String media) {
         super("video", media);
@@ -48,16 +48,27 @@ public InputPaidMediaVideo supportsStreaming(boolean supportsStreaming) {
     }
 
     public InputPaidMediaVideo thumbnail(File thumbnail) {
-        String attachName = AttachName.next();
-        attachments.put(attachName, thumbnail);
-        this.thumbnail = "attach://" + attachName;
+        this.thumbnail = addAttachment(thumbnail);
         return this;
     }
 
     public InputPaidMediaVideo thumbnail(byte[] thumbnail) {
-        String attachName = AttachName.next();
-        attachments.put(attachName, thumbnail);
-        this.thumbnail = "attach://" + attachName;
+        this.thumbnail = addAttachment(thumbnail);
+        return this;
+    }
+
+    public InputPaidMediaVideo cover(File cover) {
+        this.cover = addAttachment(cover);
+        return this;
+    }
+
+    public InputPaidMediaVideo cover(byte[] cover) {
+        this.cover = addAttachment(cover);
+        return this;
+    }
+
+    public InputPaidMediaVideo startTimestamp(Integer startTimestamp) {
+        this.start_timestamp = startTimestamp;
         return this;
     }
 

From daee3796547801f6551c9ed775f7f35d13d54d6c Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 06:06:14 +0300
Subject: [PATCH 07/18] Add video_start_timestamp parameter to ForwardMessage
 request and rewrite it to Kotlin

---
 .../telegrambot/request/ForwardMessage.java   |  27 ----
 .../telegrambot/request/ForwardMessage.kt     | 150 ++++++++++++++++++
 .../request/ForwardMessageExtension.kt        |  36 ++++-
 3 files changed, 183 insertions(+), 30 deletions(-)
 delete mode 100644 library/src/main/java/com/pengrad/telegrambot/request/ForwardMessage.java
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/request/ForwardMessage.kt

diff --git a/library/src/main/java/com/pengrad/telegrambot/request/ForwardMessage.java b/library/src/main/java/com/pengrad/telegrambot/request/ForwardMessage.java
deleted file mode 100644
index 671251e1..00000000
--- a/library/src/main/java/com/pengrad/telegrambot/request/ForwardMessage.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.pengrad.telegrambot.request;
-
-import com.pengrad.telegrambot.response.SendResponse;
-
-/**
- * stas
- * 5/1/16.
- */
-public class ForwardMessage extends BaseRequest<ForwardMessage, SendResponse> {
-
-    public ForwardMessage(Object chatId, Object fromChatId, int messageId) {
-        super(SendResponse.class);
-        add("chat_id", chatId).add("from_chat_id", fromChatId).add("message_id", messageId);
-    }
-
-    public ForwardMessage messageThreadId(Integer messageThreadId) {
-        return add("message_thread_id", messageThreadId);
-    }
-
-    public ForwardMessage disableNotification(boolean disableNotification) {
-        return add("disable_notification", disableNotification);
-    }
-    public ForwardMessage protectContent(boolean protectContent) {
-        return add("protect_content", protectContent);
-    }
-
-}
diff --git a/library/src/main/java/com/pengrad/telegrambot/request/ForwardMessage.kt b/library/src/main/java/com/pengrad/telegrambot/request/ForwardMessage.kt
new file mode 100644
index 00000000..e15013db
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/request/ForwardMessage.kt
@@ -0,0 +1,150 @@
+@file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
+
+package com.pengrad.telegrambot.request
+
+import com.pengrad.telegrambot.response.SendResponse
+import com.pengrad.telegrambot.utility.kotlin.optionalRequestParameter
+import com.pengrad.telegrambot.utility.kotlin.requestParameter
+import java.lang.Integer as JavaInteger
+import java.lang.Long as JavaLong
+
+class ForwardMessage private constructor(
+    chatId: Long?,
+    channelUsername: String?,
+
+    fromChatId: Long?,
+    fromChannelUsername: String?,
+
+    messageId: Int
+) : KBaseRequest<ForwardMessage, SendResponse>(SendResponse::class) {
+
+    constructor(chatId: Long, fromChatId: Long, messageId: Int) : this(
+        chatId = chatId,
+        channelUsername = null,
+
+        fromChatId = fromChatId,
+        fromChannelUsername = null,
+
+        messageId = messageId
+    )
+
+    /**
+     * Backwards-compatability for Java code
+     */
+    constructor(chatId: JavaLong, fromChatId: JavaLong, messageId: JavaInteger) : this(
+        chatId = chatId.toLong(),
+        fromChatId = fromChatId.toLong(),
+        messageId = messageId.toInt()
+    )
+
+
+    constructor(channelUsername: String, fromChatId: Long, messageId: Int) : this(
+        chatId = null,
+        channelUsername = channelUsername,
+
+        fromChatId = fromChatId,
+        fromChannelUsername = null,
+
+        messageId = messageId
+    )
+
+    /**
+     * Backwards-compatability for Java code
+     */
+    constructor(channelUsername: String, fromChatId: JavaLong, messageId: JavaInteger) : this(
+        channelUsername = channelUsername,
+        fromChatId = fromChatId.toLong(),
+        messageId = messageId.toInt()
+    )
+
+
+    constructor(chatId: Long, fromChannelUsername: String, messageId: Int) : this(
+        chatId = chatId,
+        channelUsername = null,
+
+        fromChatId = null,
+        fromChannelUsername = fromChannelUsername,
+
+        messageId = messageId
+    )
+
+    /**
+     * Backwards-compatability for Java code
+     */
+    constructor(chatId: JavaLong, fromChannelUsername: String, messageId: JavaInteger) : this(
+        chatId = chatId.toLong(),
+        fromChannelUsername = fromChannelUsername,
+        messageId = messageId.toInt()
+    )
+
+
+    constructor(channelUsername: String, fromChannelUsername: String, messageId: Int) : this(
+        chatId = null,
+        channelUsername = channelUsername,
+
+        fromChatId = null,
+        fromChannelUsername = fromChannelUsername,
+
+        messageId = messageId
+    )
+
+    /**
+     * Backwards-compatability for Java code
+     */
+    constructor(channelUsername: String, fromChannelUsername: String, messageId: JavaInteger) : this(
+        channelUsername = channelUsername,
+        fromChannelUsername = fromChannelUsername,
+        messageId = messageId.toInt()
+    )
+
+
+    @Deprecated("Use constructor with chatId and fromChatId or channelUsername and fromChannelUsername instead", ReplaceWith("ForwardMessage(chatId, fromChatId, messageId)"))
+    constructor(chatId: Any, fromChatId: Any, messageId: Int) : this(
+        chatId = (chatId as? Number)?.toLong(),
+        channelUsername = chatId as? String,
+        fromChatId = (fromChatId as? Number)?.toLong(),
+        fromChannelUsername = fromChatId as? String,
+        messageId = messageId
+    ) {
+        if (this.chatId == null && this.channelUsername == null) {
+            throw IllegalArgumentException("chatId parameter must be either Long or String")
+        }
+
+        if (this.fromChatId == null && this.fromChannelUsername == null) {
+            throw IllegalArgumentException("fromChatId parameter must be either Long or String")
+        }
+    }
+
+    /**
+     * Backwards-compatability for Java code
+     */
+    @Suppress("DEPRECATION")
+    @Deprecated("Use constructor with chatId and fromChatId or channelUsername and fromChannelUsername instead", ReplaceWith("ForwardMessage(chatId, fromChatId, messageId)"))
+    constructor(chatId: Any, fromChatId: Any, messageId: JavaInteger) : this(
+        chatId = chatId,
+        fromChatId = fromChatId,
+        messageId = messageId.toInt()
+    )
+
+    val chatId: Long? by optionalRequestParameter(chatId, customParameterName = "chat_id")
+    val channelUsername: String? by optionalRequestParameter(channelUsername, customParameterName = "chat_id")
+
+    val fromChatId: Long? by optionalRequestParameter(fromChatId, customParameterName = "from_chat_id")
+    val fromChannelUsername: String? by optionalRequestParameter(fromChannelUsername, customParameterName = "from_chat_id")
+
+    val messageId: Int by requestParameter(messageId)
+
+    var messageThreadId: Int? by optionalRequestParameter()
+    var disableNotification: Boolean? by optionalRequestParameter()
+    var protectContent: Boolean? by optionalRequestParameter()
+    var videoStartTimestamp: Int? by optionalRequestParameter()
+
+    fun messageThreadId(messageThreadId: Int) = applySelf { this.messageThreadId = messageThreadId }
+
+    fun disableNotification(disableNotification: Boolean) = applySelf { this.disableNotification = disableNotification }
+
+    fun protectContent(protectContent: Boolean) = applySelf { this.protectContent = protectContent }
+
+    fun videoStartTimestamp(videoStartTimestamp: Int) = applySelf { this.videoStartTimestamp = videoStartTimestamp }
+
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/ForwardMessageExtension.kt b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/ForwardMessageExtension.kt
index e8d76071..4d129742 100644
--- a/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/ForwardMessageExtension.kt
+++ b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/ForwardMessageExtension.kt
@@ -9,11 +9,41 @@ inline fun TelegramAware.forwardMessage(
     fromChatId: Long,
     messageId: Int,
     modifier: ForwardMessage.() -> Unit = {}
-) = this.execute(ForwardMessage(chatId, fromChatId, messageId), modifier)
+) = this.execute(ForwardMessage(
+    chatId = chatId,
+    fromChatId = fromChatId,
+    messageId = messageId
+), modifier)
 
 inline fun TelegramAware.forwardMessage(
-    chatId: String,
+    channelUsername: String,
     fromChatId: Long,
     messageId: Int,
     modifier: ForwardMessage.() -> Unit = {}
-) = this.execute(ForwardMessage(chatId, fromChatId, messageId), modifier)
\ No newline at end of file
+) = this.execute(ForwardMessage(
+    channelUsername = channelUsername,
+    fromChatId = fromChatId,
+    messageId = messageId
+), modifier)
+
+inline fun TelegramAware.forwardMessage(
+    chatId: Long,
+    fromChannelUsername: String,
+    messageId: Int,
+    modifier: ForwardMessage.() -> Unit = {}
+) = this.execute(ForwardMessage(
+    chatId = chatId,
+    fromChannelUsername = fromChannelUsername,
+    messageId = messageId
+), modifier)
+
+inline fun TelegramAware.forwardMessage(
+    channelUsername: String,
+    fromChannelUsername: String,
+    messageId: Int,
+    modifier: ForwardMessage.() -> Unit = {}
+) = this.execute(ForwardMessage(
+    channelUsername = channelUsername,
+    fromChannelUsername = fromChannelUsername,
+    messageId = messageId
+), modifier)
\ No newline at end of file

From 1336b729ce36c92461f9ab290fc9498c14924388 Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 15:34:33 +0300
Subject: [PATCH 08/18] Add video_start_timestamp parameter to CopyMessage
 request and rewrite it to Kotlin

---
 .../telegrambot/request/CopyMessage.java      |  74 -------
 .../telegrambot/request/CopyMessage.kt        | 200 ++++++++++++++++++
 .../extension/request/CopyMessageExtension.kt |  49 +++++
 3 files changed, 249 insertions(+), 74 deletions(-)
 delete mode 100644 library/src/main/java/com/pengrad/telegrambot/request/CopyMessage.java
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/request/CopyMessage.kt
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/CopyMessageExtension.kt

diff --git a/library/src/main/java/com/pengrad/telegrambot/request/CopyMessage.java b/library/src/main/java/com/pengrad/telegrambot/request/CopyMessage.java
deleted file mode 100644
index c14fcbb4..00000000
--- a/library/src/main/java/com/pengrad/telegrambot/request/CopyMessage.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.pengrad.telegrambot.request;
-
-import com.pengrad.telegrambot.model.MessageEntity;
-import com.pengrad.telegrambot.model.request.ReplyParameters;
-import com.pengrad.telegrambot.model.request.Keyboard;
-import com.pengrad.telegrambot.model.request.ParseMode;
-import com.pengrad.telegrambot.response.MessageIdResponse;
-
-/**
- * Stas Parshin
- * 06 November 2020
- */
-public class CopyMessage extends BaseRequest<CopyMessage, MessageIdResponse> {
-
-    public CopyMessage(Object chatId, Object fromChatId, int messageId) {
-        super(MessageIdResponse.class);
-        add("chat_id", chatId).add("from_chat_id", fromChatId).add("message_id", messageId);
-    }
-
-    public CopyMessage messageThreadId(Integer messageThreadId) {
-        return add("message_thread_id", messageThreadId);
-    }
-
-    public CopyMessage caption(String caption) {
-        return add("caption", caption);
-    }
-
-    public CopyMessage parseMode(ParseMode parseMode) {
-        return add("parse_mode", parseMode.name());
-    }
-
-    public CopyMessage captionEntities(MessageEntity... entities) {
-        return add("caption_entities", entities);
-    }
-
-    public CopyMessage replyParameters(ReplyParameters replyParameters) {
-        return add("reply_parameters", replyParameters);
-    }
-
-    /*
-        @deprecated Use replyParameters instead
-     */
-    public CopyMessage allowSendingWithoutReply(boolean allowSendingWithoutReply) {
-        return add("allow_sending_without_reply", allowSendingWithoutReply);
-    }
-
-    /*
-        @deprecated Use replyParameters instead
-    */
-    public CopyMessage replyToMessageId(int replyToMessageId) {
-        return add("reply_to_message_id", replyToMessageId);
-    }
-
-    public CopyMessage replyMarkup(Keyboard replyMarkup) {
-        return add("reply_markup", replyMarkup);
-    }
-
-    public CopyMessage showCaptionAboveMedia(boolean showCaptionAboveMedia) {
-        return add("show_caption_above_media", showCaptionAboveMedia);
-    }
-
-    public CopyMessage disableNotification(boolean disableNotification) {
-        return add("disable_notification", disableNotification);
-    }
-
-    public CopyMessage protectContent(boolean protectContent) {
-        return add("protect_content", protectContent);
-    }
-
-    public CopyMessage allowPaidBroadcast(boolean allowPaidBroadcast) {
-        return add("allow_paid_broadcast", allowPaidBroadcast);
-    }
-
-}
diff --git a/library/src/main/java/com/pengrad/telegrambot/request/CopyMessage.kt b/library/src/main/java/com/pengrad/telegrambot/request/CopyMessage.kt
new file mode 100644
index 00000000..91b65a00
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/request/CopyMessage.kt
@@ -0,0 +1,200 @@
+package com.pengrad.telegrambot.request
+
+import com.pengrad.telegrambot.model.MessageEntity
+import com.pengrad.telegrambot.model.request.Keyboard
+import com.pengrad.telegrambot.model.request.ParseMode
+import com.pengrad.telegrambot.model.request.ReplyParameters
+import com.pengrad.telegrambot.response.MessageIdResponse
+import com.pengrad.telegrambot.utility.kotlin.optionalRequestParameter
+import com.pengrad.telegrambot.utility.kotlin.requestParameter
+
+class CopyMessage private constructor(
+    chatId: Long?,
+    channelUsername: String?,
+
+    fromChatId: Long?,
+    fromChannelUsername: String?,
+
+    messageId: Int
+) : KBaseRequest<CopyMessage, MessageIdResponse>(MessageIdResponse::class) {
+
+    constructor(chatId: Long, fromChatId: Long, messageId: Int) : this(
+        chatId = chatId,
+        channelUsername = null,
+
+        fromChatId = fromChatId,
+        fromChannelUsername = null,
+
+        messageId = messageId
+    )
+
+    /**
+     * Backwards-compatability for Java code
+     */
+    constructor(chatId: java.lang.Long, fromChatId: java.lang.Long, messageId: Integer) : this(
+        chatId = chatId.toLong(),
+        fromChatId = fromChatId.toLong(),
+        messageId = messageId.toInt()
+    )
+
+
+    constructor(channelUsername: String, fromChatId: Long, messageId: Int) : this(
+        chatId = null,
+        channelUsername = channelUsername,
+
+        fromChatId = fromChatId,
+        fromChannelUsername = null,
+
+        messageId = messageId
+    )
+
+    /**
+     * Backwards-compatability for Java code
+     */
+    constructor(channelUsername: String, fromChatId: java.lang.Long, messageId: Integer) : this(
+        channelUsername = channelUsername,
+        fromChatId = fromChatId.toLong(),
+        messageId = messageId.toInt()
+    )
+
+
+    constructor(chatId: Long, fromChannelUsername: String, messageId: Int) : this(
+        chatId = chatId,
+        channelUsername = null,
+
+        fromChatId = null,
+        fromChannelUsername = fromChannelUsername,
+
+        messageId = messageId
+    )
+
+    /**
+     * Backwards-compatability for Java code
+     */
+    constructor(chatId: java.lang.Long, fromChannelUsername: String, messageId: Integer) : this(
+        chatId = chatId.toLong(),
+        fromChannelUsername = fromChannelUsername,
+        messageId = messageId.toInt()
+    )
+
+
+    constructor(channelUsername: String, fromChannelUsername: String, messageId: Int) : this(
+        chatId = null,
+        channelUsername = channelUsername,
+
+        fromChatId = null,
+        fromChannelUsername = fromChannelUsername,
+
+        messageId = messageId
+    )
+
+    /**
+     * Backwards-compatability for Java code
+     */
+    constructor(channelUsername: String, fromChannelUsername: String, messageId: Integer) : this(
+        channelUsername = channelUsername,
+        fromChannelUsername = fromChannelUsername,
+        messageId = messageId.toInt()
+    )
+
+
+    @Deprecated("Use constructor with chatId and fromChatId or channelUsername and fromChannelUsername instead", ReplaceWith("ForwardMessage(chatId, fromChatId, messageId)"))
+    constructor(chatId: Any, fromChatId: Any, messageId: Int) : this(
+        chatId = (chatId as? Number)?.toLong(),
+        channelUsername = chatId as? String,
+        fromChatId = (fromChatId as? Number)?.toLong(),
+        fromChannelUsername = fromChatId as? String,
+        messageId = messageId
+    ) {
+        if (this.chatId == null && this.channelUsername == null) {
+            throw IllegalArgumentException("chatId parameter must be either Long or String")
+        }
+
+        if (this.fromChatId == null && this.fromChannelUsername == null) {
+            throw IllegalArgumentException("fromChatId parameter must be either Long or String")
+        }
+    }
+
+    /**
+     * Backwards-compatability for Java code
+     */
+    @Suppress("DEPRECATION")
+    @Deprecated("Use constructor with chatId and fromChatId or channelUsername and fromChannelUsername instead", ReplaceWith("ForwardMessage(chatId, fromChatId, messageId)"))
+    constructor(chatId: Any, fromChatId: Any, messageId: Integer) : this(
+        chatId = chatId,
+        fromChatId = fromChatId,
+        messageId = messageId.toInt()
+    )
+
+    val chatId: Long? by optionalRequestParameter(chatId, customParameterName = "chat_id")
+    val channelUsername: String? by optionalRequestParameter(channelUsername, customParameterName = "chat_id")
+
+    val fromChatId: Long? by optionalRequestParameter(fromChatId, customParameterName = "from_chat_id")
+    val fromChannelUsername: String? by optionalRequestParameter(fromChannelUsername, customParameterName = "from_chat_id")
+
+    val messageId: Int by requestParameter(messageId)
+
+    var messageThreadId: Int? by optionalRequestParameter()
+
+    var caption: String? by optionalRequestParameter()
+    var parseMode: ParseMode? by optionalRequestParameter()
+    var captionEntities: List<MessageEntity>? by optionalRequestParameter()
+
+    var replyParameters: ReplyParameters? by optionalRequestParameter()
+    @Deprecated("Use replyParameters instead")
+    private var replyToMessageId: Int? by optionalRequestParameter()
+    @Deprecated("Use replyParameters instead")
+    private var allowSendingWithoutReply: Boolean? by optionalRequestParameter()
+
+    var replyMarkup: Keyboard? by optionalRequestParameter()
+    var showCaptionAboveMedia: Boolean? by optionalRequestParameter()
+    var disableNotification: Boolean? by optionalRequestParameter()
+    var protectContent: Boolean? by optionalRequestParameter()
+    var videoStartTimestamp: Int? by optionalRequestParameter()
+    var allowPaidBroadcast: Boolean? by optionalRequestParameter()
+
+    fun messageThreadId(messageThreadId: Int) = applySelf { this.messageThreadId = messageThreadId }
+
+    fun caption(caption: String) = applySelf { this.caption = caption }
+
+    fun parseMode(parseMode: ParseMode) = applySelf { this.parseMode = parseMode }
+
+    fun captionEntities(captionEntities: List<MessageEntity>) = applySelf { this.captionEntities = captionEntities }
+
+    fun captionEntities(vararg captionEntities: MessageEntity) = applySelf { this.captionEntities = captionEntities.toList() }
+
+    fun replyParameters(parameters: ReplyParameters) = applySelf { this.replyParameters = parameters }
+
+    @Suppress("DEPRECATION")
+    @Deprecated(
+        message = "Use replyParameters instead",
+        ReplaceWith(
+            expression = "replyParameters(ReplyParameters(replyToMessageId))",
+            imports = ["com.pengrad.telegrambot.model.request.ReplyParameters"]
+        )
+    )
+    fun replyToMessageId(replyToMessageId: Int) = applySelf { this.replyToMessageId = replyToMessageId }
+
+    @Suppress("DEPRECATION")
+    @Deprecated(
+        message = "Use replyParameters instead",
+        ReplaceWith(
+            expression = "replyParameters(ReplyParameters(messageId).allowSendingWithoutReply(allowSendingWithoutReply))",
+            imports = ["com.pengrad.telegrambot.model.request.ReplyParameters"]
+        )
+    )
+    fun allowSendingWithoutReply(allowSendingWithoutReply: Boolean) = applySelf { this.allowSendingWithoutReply = allowSendingWithoutReply }
+
+    fun replyMarkup(replyMarkup: Keyboard) = applySelf { this.replyMarkup = replyMarkup }
+
+    fun showCaptionAboveMedia(showCaptionAboveMedia: Boolean) = applySelf { this.showCaptionAboveMedia = showCaptionAboveMedia }
+
+    fun disableNotification(disableNotification: Boolean) = applySelf { this.disableNotification = disableNotification }
+
+    fun protectContent(protectContent: Boolean) = applySelf { this.protectContent = protectContent }
+
+    fun videoStartTimestamp(videoStartTimestamp: Int) = applySelf { this.videoStartTimestamp = videoStartTimestamp }
+
+    fun allowPaidBroadcast(allowPaidBroadcast: Boolean) = applySelf { this.allowPaidBroadcast = allowPaidBroadcast }
+
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/CopyMessageExtension.kt b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/CopyMessageExtension.kt
new file mode 100644
index 00000000..c59007c6
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/CopyMessageExtension.kt
@@ -0,0 +1,49 @@
+package com.pengrad.telegrambot.utility.kotlin.extension.request
+
+import com.pengrad.telegrambot.TelegramAware
+import com.pengrad.telegrambot.request.CopyMessage
+import com.pengrad.telegrambot.utility.kotlin.extension.execute
+
+inline fun TelegramAware.copyMessage(
+    chatId: Long,
+    fromChatId: Long,
+    messageId: Int,
+    modifier: CopyMessage.() -> Unit = {}
+) = this.execute(CopyMessage(
+    chatId = chatId,
+    fromChatId = fromChatId,
+    messageId = messageId
+), modifier)
+
+inline fun TelegramAware.copyMessage(
+    channelUsername: String,
+    fromChatId: Long,
+    messageId: Int,
+    modifier: CopyMessage.() -> Unit = {}
+) = this.execute(CopyMessage(
+    channelUsername = channelUsername,
+    fromChatId = fromChatId,
+    messageId = messageId
+), modifier)
+
+inline fun TelegramAware.copyMessage(
+    chatId: Long,
+    fromChannelUsername: String,
+    messageId: Int,
+    modifier: CopyMessage.() -> Unit = {}
+) = this.execute(CopyMessage(
+    chatId = chatId,
+    fromChannelUsername = fromChannelUsername,
+    messageId = messageId
+), modifier)
+
+inline fun TelegramAware.copyMessage(
+    channelUsername: String,
+    fromChannelUsername: String,
+    messageId: Int,
+    modifier: CopyMessage.() -> Unit = {}
+) = this.execute(CopyMessage(
+    channelUsername = channelUsername,
+    fromChannelUsername = fromChannelUsername,
+    messageId = messageId
+), modifier)
\ No newline at end of file

From 934985fa07491de9753e7820485ac7f4983aece3 Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 15:44:35 +0300
Subject: [PATCH 09/18] Create VerifyUser request

---
 .../pengrad/telegrambot/request/VerifyUser.kt    | 16 ++++++++++++++++
 .../extension/request/VerifyUserExtenstion.kt    | 16 ++++++++++++++++
 2 files changed, 32 insertions(+)
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/request/VerifyUser.kt
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/VerifyUserExtenstion.kt

diff --git a/library/src/main/java/com/pengrad/telegrambot/request/VerifyUser.kt b/library/src/main/java/com/pengrad/telegrambot/request/VerifyUser.kt
new file mode 100644
index 00000000..11ca6217
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/request/VerifyUser.kt
@@ -0,0 +1,16 @@
+package com.pengrad.telegrambot.request
+
+import com.pengrad.telegrambot.response.BaseResponse
+import com.pengrad.telegrambot.utility.kotlin.optionalRequestParameter
+import com.pengrad.telegrambot.utility.kotlin.requestParameter
+
+class VerifyUser(
+    userId: Long
+) : KBaseRequest<VerifyUser, BaseResponse>(BaseResponse::class) {
+
+    val userId: Long by requestParameter(userId)
+    var customDescription: String? by optionalRequestParameter()
+
+    fun customDescription(customDescription: String) = applySelf { this.customDescription = customDescription }
+
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/VerifyUserExtenstion.kt b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/VerifyUserExtenstion.kt
new file mode 100644
index 00000000..6fbd4079
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/VerifyUserExtenstion.kt
@@ -0,0 +1,16 @@
+package com.pengrad.telegrambot.utility.kotlin.extension.request
+
+import com.pengrad.telegrambot.TelegramAware
+import com.pengrad.telegrambot.request.VerifyUser
+import com.pengrad.telegrambot.utility.kotlin.extension.execute
+
+inline fun TelegramAware.verifyUser(
+    userId: Long,
+    customDescription: String? = null,
+    modifier: VerifyUser.() -> Unit = {}
+) = this.execute(VerifyUser(
+    userId = userId
+)) {
+    this.customDescription = customDescription
+    modifier()
+}
\ No newline at end of file

From 82c41681c6dd2f7564aa2eafdd4b1a088ffc5394 Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 15:47:50 +0300
Subject: [PATCH 10/18] Create VerifyChat request

---
 .../pengrad/telegrambot/request/VerifyChat.kt | 29 +++++++++++++++++++
 .../extension/request/VerifyChatExtenstion.kt | 28 ++++++++++++++++++
 2 files changed, 57 insertions(+)
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/request/VerifyChat.kt
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/VerifyChatExtenstion.kt

diff --git a/library/src/main/java/com/pengrad/telegrambot/request/VerifyChat.kt b/library/src/main/java/com/pengrad/telegrambot/request/VerifyChat.kt
new file mode 100644
index 00000000..2ecedead
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/request/VerifyChat.kt
@@ -0,0 +1,29 @@
+package com.pengrad.telegrambot.request
+
+import com.pengrad.telegrambot.response.BaseResponse
+import com.pengrad.telegrambot.utility.kotlin.optionalRequestParameter
+import com.pengrad.telegrambot.utility.kotlin.requestParameter
+
+class VerifyChat private constructor(
+    chatId: Long?,
+    channelUsername: String?
+) : KBaseRequest<VerifyChat, BaseResponse>(BaseResponse::class) {
+
+    constructor(chatId: Long) : this(
+        chatId = chatId,
+        channelUsername = null
+    )
+
+    constructor(channelUsername: String) : this(
+        chatId = null,
+        channelUsername = channelUsername
+    )
+
+    val chatId: Long? by optionalRequestParameter(chatId, customParameterName = "chat_id")
+    val channelUsername: String? by optionalRequestParameter(channelUsername, customParameterName = "chat_id")
+
+    var customDescription: String? by optionalRequestParameter()
+
+    fun customDescription(customDescription: String) = applySelf { this.customDescription = customDescription }
+
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/VerifyChatExtenstion.kt b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/VerifyChatExtenstion.kt
new file mode 100644
index 00000000..f290d81d
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/VerifyChatExtenstion.kt
@@ -0,0 +1,28 @@
+package com.pengrad.telegrambot.utility.kotlin.extension.request
+
+import com.pengrad.telegrambot.TelegramAware
+import com.pengrad.telegrambot.request.VerifyChat
+import com.pengrad.telegrambot.request.VerifyUser
+import com.pengrad.telegrambot.utility.kotlin.extension.execute
+
+inline fun TelegramAware.verifyChat(
+    chatId: Long,
+    customDescription: String? = null,
+    modifier: VerifyChat.() -> Unit = {}
+) = this.execute(VerifyChat(
+    chatId = chatId
+)) {
+    this.customDescription = customDescription
+    modifier()
+}
+
+inline fun TelegramAware.verifyChat(
+    channelUsername: String,
+    customDescription: String? = null,
+    modifier: VerifyChat.() -> Unit = {}
+) = this.execute(VerifyChat(
+    channelUsername = channelUsername
+)) {
+    this.customDescription = customDescription
+    modifier()
+}
\ No newline at end of file

From 9d566059babd3fb77b56c3476f2ea37dbc620883 Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 15:51:56 +0300
Subject: [PATCH 11/18] Create RemoveUserVerification request

---
 .../telegrambot/request/RemoveUserVerification.kt    | 12 ++++++++++++
 .../request/RemoveUserVerificationExtension.kt       | 12 ++++++++++++
 2 files changed, 24 insertions(+)
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/request/RemoveUserVerification.kt
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/RemoveUserVerificationExtension.kt

diff --git a/library/src/main/java/com/pengrad/telegrambot/request/RemoveUserVerification.kt b/library/src/main/java/com/pengrad/telegrambot/request/RemoveUserVerification.kt
new file mode 100644
index 00000000..c14780a9
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/request/RemoveUserVerification.kt
@@ -0,0 +1,12 @@
+package com.pengrad.telegrambot.request
+
+import com.pengrad.telegrambot.response.BaseResponse
+import com.pengrad.telegrambot.utility.kotlin.requestParameter
+
+class RemoveUserVerification(
+    userId: Long
+) : KBaseRequest<RemoveUserVerification, BaseResponse>(BaseResponse::class) {
+
+    val userId: Long by requestParameter(userId)
+
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/RemoveUserVerificationExtension.kt b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/RemoveUserVerificationExtension.kt
new file mode 100644
index 00000000..e140b9de
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/RemoveUserVerificationExtension.kt
@@ -0,0 +1,12 @@
+package com.pengrad.telegrambot.utility.kotlin.extension.request
+
+import com.pengrad.telegrambot.TelegramAware
+import com.pengrad.telegrambot.request.RemoveUserVerification
+import com.pengrad.telegrambot.utility.kotlin.extension.execute
+
+inline fun TelegramAware.removeUserVerification(
+    userId: Long,
+    modifier: RemoveUserVerification.() -> Unit = {}
+) = this.execute(RemoveUserVerification(
+    userId = userId
+), modifier)
\ No newline at end of file

From 3a941d9d2da746fcfa6bf10b91d46c10d6f009ea Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 15:54:15 +0300
Subject: [PATCH 12/18] Create RemoveChatVerification request

---
 .../request/RemoveChatVerification.kt         | 25 +++++++++++++++++++
 .../RemoveChatVerificationExtension.kt        | 20 +++++++++++++++
 2 files changed, 45 insertions(+)
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/request/RemoveChatVerification.kt
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/RemoveChatVerificationExtension.kt

diff --git a/library/src/main/java/com/pengrad/telegrambot/request/RemoveChatVerification.kt b/library/src/main/java/com/pengrad/telegrambot/request/RemoveChatVerification.kt
new file mode 100644
index 00000000..6df633f5
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/request/RemoveChatVerification.kt
@@ -0,0 +1,25 @@
+package com.pengrad.telegrambot.request
+
+import com.pengrad.telegrambot.response.BaseResponse
+import com.pengrad.telegrambot.utility.kotlin.optionalRequestParameter
+import com.pengrad.telegrambot.utility.kotlin.requestParameter
+
+class RemoveChatVerification(
+    chatId: Long?,
+    channelUsername: String?
+) : KBaseRequest<RemoveChatVerification, BaseResponse>(BaseResponse::class) {
+
+    constructor(chatId: Long) : this(
+        chatId = chatId,
+        channelUsername = null
+    )
+
+    constructor(channelUsername: String) : this(
+        chatId = null,
+        channelUsername = channelUsername
+    )
+
+    val chatId: Long? by optionalRequestParameter(chatId, customParameterName = "chat_id")
+    val channelUsername: String? by optionalRequestParameter(channelUsername, customParameterName = "chat_id")
+
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/RemoveChatVerificationExtension.kt b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/RemoveChatVerificationExtension.kt
new file mode 100644
index 00000000..d99afa19
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/extension/request/RemoveChatVerificationExtension.kt
@@ -0,0 +1,20 @@
+package com.pengrad.telegrambot.utility.kotlin.extension.request
+
+import com.pengrad.telegrambot.TelegramAware
+import com.pengrad.telegrambot.request.RemoveChatVerification
+import com.pengrad.telegrambot.request.RemoveUserVerification
+import com.pengrad.telegrambot.utility.kotlin.extension.execute
+
+inline fun TelegramAware.removeChatVerification(
+    chatId: Long,
+    modifier: RemoveChatVerification.() -> Unit = {}
+) = this.execute(RemoveChatVerification(
+    chatId = chatId
+), modifier)
+
+inline fun TelegramAware.removeChatVerification(
+    channelUsername: String,
+    modifier: RemoveChatVerification.() -> Unit = {}
+) = this.execute(RemoveChatVerification(
+    channelUsername = channelUsername
+), modifier)
\ No newline at end of file

From 560e41d00a120b3f89d082758543950503fe17d4 Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 15:56:07 +0300
Subject: [PATCH 13/18] Add upgradeStarCount field to Gift, fix nullability for
 totalCount and remainingCount fields

---
 .../src/main/java/com/pengrad/telegrambot/model/gift/Gift.kt | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/library/src/main/java/com/pengrad/telegrambot/model/gift/Gift.kt b/library/src/main/java/com/pengrad/telegrambot/model/gift/Gift.kt
index eef53655..810f7f2e 100644
--- a/library/src/main/java/com/pengrad/telegrambot/model/gift/Gift.kt
+++ b/library/src/main/java/com/pengrad/telegrambot/model/gift/Gift.kt
@@ -6,6 +6,7 @@ data class Gift(
     @get:JvmName("id") val id: String,
     @get:JvmName("sticker") val sticker: Sticker,
     @get:JvmName("starCount") val starCount: Int,
-    @get:JvmName("totalCount") val totalCount: Int,
-    @get:JvmName("remainingCount") val remainingCount: Int
+    @get:JvmName("upgradeStarCount") val upgradeStarCount: Int? = null,
+    @get:JvmName("totalCount") val totalCount: Int? = null,
+    @get:JvmName("remainingCount") val remainingCount: Int? = null
 )

From b36bdba3883eddebc920128e46ebcb80cde93d7a Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 15:57:19 +0300
Subject: [PATCH 14/18] Add payForUpgrade parameter to SendGift request

---
 .../src/main/java/com/pengrad/telegrambot/request/SendGift.kt   | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/library/src/main/java/com/pengrad/telegrambot/request/SendGift.kt b/library/src/main/java/com/pengrad/telegrambot/request/SendGift.kt
index a98cdeb1..a783a19c 100644
--- a/library/src/main/java/com/pengrad/telegrambot/request/SendGift.kt
+++ b/library/src/main/java/com/pengrad/telegrambot/request/SendGift.kt
@@ -70,6 +70,8 @@ class SendGift private constructor(
 
     val giftId: String by requestParameter(giftId)
 
+    var payForUpgrade: Boolean? by  optionalRequestParameter()
+
     var text: String? by optionalRequestParameter()
     var textParseMode: ParseMode? by optionalRequestParameter(valueMapper = { it?.name })
     var textEntities: Array<MessageEntity>? by optionalRequestParameter()

From e2d0031d68c56d297fdd59064a2d6085ba7507de Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 16:06:24 +0300
Subject: [PATCH 15/18] Deprecate hideUrl method in InlineQueryResultArticle

---
 .../telegrambot/model/request/InlineQueryResultArticle.java | 6 +++++-
 .../test/java/com/pengrad/telegrambot/TelegramBotTest.java  | 2 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/library/src/main/java/com/pengrad/telegrambot/model/request/InlineQueryResultArticle.java b/library/src/main/java/com/pengrad/telegrambot/model/request/InlineQueryResultArticle.java
index 6c6e3edd..e19de28d 100644
--- a/library/src/main/java/com/pengrad/telegrambot/model/request/InlineQueryResultArticle.java
+++ b/library/src/main/java/com/pengrad/telegrambot/model/request/InlineQueryResultArticle.java
@@ -34,8 +34,12 @@ public InlineQueryResultArticle url(String url) {
         return this;
     }
 
+    /**
+     * @deprecated hideUrl method is removed since <a href="https://core.telegram.org/bots/api#january-1-2025">Bot API 8.2</a>. This method removes url parameter to emulate hideUrl parameter behavior. It may break your code logic. Pass an empty string as url instead.
+     */
+    @Deprecated
     public InlineQueryResultArticle hideUrl(Boolean hideUrl) {
-        this.hide_url = hideUrl;
+        this.url = null;
         return this;
     }
 
diff --git a/library/src/test/java/com/pengrad/telegrambot/TelegramBotTest.java b/library/src/test/java/com/pengrad/telegrambot/TelegramBotTest.java
index 40fd2d93..df0637f3 100644
--- a/library/src/test/java/com/pengrad/telegrambot/TelegramBotTest.java
+++ b/library/src/test/java/com/pengrad/telegrambot/TelegramBotTest.java
@@ -354,7 +354,7 @@ public void answerInline() {
                         new InputTextMessageContent("message")
                                 .entities(new MessageEntity(MessageEntity.Type.bold, 0, 2))
                                 .disableWebPagePreview(false).parseMode(ParseMode.HTML))
-                        .url(someUrl).hideUrl(true).description("desc")
+                        .url(someUrl).description("desc")
                         .thumbUrl(someUrl).thumbHeight(100).thumbWidth(100),
                 new InlineQueryResultArticle("2", "title",
                         new InputContactMessageContent("123123123", "na,e").lastName("lastName").vcard("qr vcard")),

From e0129501ad9a27e97a01c045d8aa57d496cbe84b Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 16:16:25 +0300
Subject: [PATCH 16/18] Fix: create only-required parameters constructor for
 InlineQueryResultVideo

---
 .../model/request/InlineQueryResultVideo.java      | 14 +++++++++++++-
 .../com/pengrad/telegrambot/TelegramBotTest.java   |  6 ++++--
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/library/src/main/java/com/pengrad/telegrambot/model/request/InlineQueryResultVideo.java b/library/src/main/java/com/pengrad/telegrambot/model/request/InlineQueryResultVideo.java
index 0c86b20d..d9ed3415 100644
--- a/library/src/main/java/com/pengrad/telegrambot/model/request/InlineQueryResultVideo.java
+++ b/library/src/main/java/com/pengrad/telegrambot/model/request/InlineQueryResultVideo.java
@@ -24,17 +24,29 @@ public class InlineQueryResultVideo extends InlineQueryResult<InlineQueryResultV
     private Integer video_duration;
     private String description;
 
+    /**
+     * @deprecated use a constructor without messageText and inputMessageContent(new InputTextMessageContent(messageText)) instead
+     */
+    @Deprecated
     public InlineQueryResultVideo(String id, String videoUrl, String mimeType, String messageText, String thumbUrl, String title) {
         this(id, videoUrl, mimeType, new InputTextMessageContent(messageText), thumbUrl, title);
     }
 
+    /**
+     * @deprecated use a constructor without inputMessageContent and inputMessageContent(inputMessageContent) instead
+     */
+    @Deprecated
     public InlineQueryResultVideo(String id, String videoUrl, String mimeType, InputMessageContent inputMessageContent, String thumbnailUrl, String title) {
+        this(id, videoUrl, mimeType, thumbnailUrl, title);
+        inputMessageContent(inputMessageContent);
+    }
+
+    public InlineQueryResultVideo(String id, String videoUrl, String mimeType, String thumbnailUrl, String title) {
         super("video", id);
         this.video_url = videoUrl;
         this.mime_type = mimeType;
         this.thumbnail_url = thumbnailUrl;
         this.title = title;
-        inputMessageContent(inputMessageContent);
     }
 
     public InlineQueryResultVideo caption(String caption) {
diff --git a/library/src/test/java/com/pengrad/telegrambot/TelegramBotTest.java b/library/src/test/java/com/pengrad/telegrambot/TelegramBotTest.java
index df0637f3..78ebe78c 100644
--- a/library/src/test/java/com/pengrad/telegrambot/TelegramBotTest.java
+++ b/library/src/test/java/com/pengrad/telegrambot/TelegramBotTest.java
@@ -397,8 +397,10 @@ public void answerInline() {
                         .googlePlaceId("ggId").googlePlaceType("gType")
                         .thumbUrl(someUrl).thumbHeight(100).thumbWidth(100)
                         .thumbnailUrl(someUrl).thumbnailHeight(100).thumbnailWidth(100),
-                new InlineQueryResultVideo("15", someUrl, VIDEO_MIME_TYPE, "text", someUrl, "title").caption("cap <b>bold</b>").parseMode(ParseMode.HTML)
-                        .videoWidth(100).videoHeight(100).videoDuration(100).description("desc"),
+                new InlineQueryResultVideo("15", someUrl, VIDEO_MIME_TYPE, someUrl, "title")
+                    .inputMessageContent(new InputTextMessageContent("text"))
+                    .caption("cap <b>bold</b>").parseMode(ParseMode.HTML)
+                    .videoWidth(100).videoHeight(100).videoDuration(100).description("desc"),
                 new InlineQueryResultVoice("16", someUrl, "title").caption("cap <b>bold</b>").parseMode(ParseMode.HTML).voiceDuration(100),
                 new InlineQueryResultCachedAudio("17", audioFileId).caption("cap <b>bold</b>").parseMode(ParseMode.HTML),
                 new InlineQueryResultCachedDocument("18", stickerId, "title").caption("cap <b>bold</b>").parseMode(ParseMode.HTML).description("desc"),

From de01317229e3f711f9b59e2cbbccaecef599bc58 Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Wed, 19 Feb 2025 16:49:45 +0300
Subject: [PATCH 17/18] Create JavaCompatabilityUtility

---
 .../com/pengrad/telegrambot/request/CopyMessage.kt   | 12 +++++++-----
 .../pengrad/telegrambot/request/ForwardMessage.kt    |  4 ++--
 .../utility/kotlin/JavaCompatabilityUtility.kt       |  7 +++++++
 3 files changed, 16 insertions(+), 7 deletions(-)
 create mode 100644 library/src/main/java/com/pengrad/telegrambot/utility/kotlin/JavaCompatabilityUtility.kt

diff --git a/library/src/main/java/com/pengrad/telegrambot/request/CopyMessage.kt b/library/src/main/java/com/pengrad/telegrambot/request/CopyMessage.kt
index 91b65a00..9245e49d 100644
--- a/library/src/main/java/com/pengrad/telegrambot/request/CopyMessage.kt
+++ b/library/src/main/java/com/pengrad/telegrambot/request/CopyMessage.kt
@@ -5,6 +5,8 @@ import com.pengrad.telegrambot.model.request.Keyboard
 import com.pengrad.telegrambot.model.request.ParseMode
 import com.pengrad.telegrambot.model.request.ReplyParameters
 import com.pengrad.telegrambot.response.MessageIdResponse
+import com.pengrad.telegrambot.utility.kotlin.JavaInteger
+import com.pengrad.telegrambot.utility.kotlin.JavaLong
 import com.pengrad.telegrambot.utility.kotlin.optionalRequestParameter
 import com.pengrad.telegrambot.utility.kotlin.requestParameter
 
@@ -31,7 +33,7 @@ class CopyMessage private constructor(
     /**
      * Backwards-compatability for Java code
      */
-    constructor(chatId: java.lang.Long, fromChatId: java.lang.Long, messageId: Integer) : this(
+    constructor(chatId: JavaLong, fromChatId: JavaLong, messageId: JavaInteger) : this(
         chatId = chatId.toLong(),
         fromChatId = fromChatId.toLong(),
         messageId = messageId.toInt()
@@ -51,7 +53,7 @@ class CopyMessage private constructor(
     /**
      * Backwards-compatability for Java code
      */
-    constructor(channelUsername: String, fromChatId: java.lang.Long, messageId: Integer) : this(
+    constructor(channelUsername: String, fromChatId: JavaLong, messageId: JavaInteger) : this(
         channelUsername = channelUsername,
         fromChatId = fromChatId.toLong(),
         messageId = messageId.toInt()
@@ -71,7 +73,7 @@ class CopyMessage private constructor(
     /**
      * Backwards-compatability for Java code
      */
-    constructor(chatId: java.lang.Long, fromChannelUsername: String, messageId: Integer) : this(
+    constructor(chatId: JavaLong, fromChannelUsername: String, messageId: JavaInteger) : this(
         chatId = chatId.toLong(),
         fromChannelUsername = fromChannelUsername,
         messageId = messageId.toInt()
@@ -91,7 +93,7 @@ class CopyMessage private constructor(
     /**
      * Backwards-compatability for Java code
      */
-    constructor(channelUsername: String, fromChannelUsername: String, messageId: Integer) : this(
+    constructor(channelUsername: String, fromChannelUsername: String, messageId: JavaInteger) : this(
         channelUsername = channelUsername,
         fromChannelUsername = fromChannelUsername,
         messageId = messageId.toInt()
@@ -120,7 +122,7 @@ class CopyMessage private constructor(
      */
     @Suppress("DEPRECATION")
     @Deprecated("Use constructor with chatId and fromChatId or channelUsername and fromChannelUsername instead", ReplaceWith("ForwardMessage(chatId, fromChatId, messageId)"))
-    constructor(chatId: Any, fromChatId: Any, messageId: Integer) : this(
+    constructor(chatId: Any, fromChatId: Any, messageId: JavaInteger) : this(
         chatId = chatId,
         fromChatId = fromChatId,
         messageId = messageId.toInt()
diff --git a/library/src/main/java/com/pengrad/telegrambot/request/ForwardMessage.kt b/library/src/main/java/com/pengrad/telegrambot/request/ForwardMessage.kt
index e15013db..58c071c7 100644
--- a/library/src/main/java/com/pengrad/telegrambot/request/ForwardMessage.kt
+++ b/library/src/main/java/com/pengrad/telegrambot/request/ForwardMessage.kt
@@ -3,10 +3,10 @@
 package com.pengrad.telegrambot.request
 
 import com.pengrad.telegrambot.response.SendResponse
+import com.pengrad.telegrambot.utility.kotlin.JavaInteger
+import com.pengrad.telegrambot.utility.kotlin.JavaLong
 import com.pengrad.telegrambot.utility.kotlin.optionalRequestParameter
 import com.pengrad.telegrambot.utility.kotlin.requestParameter
-import java.lang.Integer as JavaInteger
-import java.lang.Long as JavaLong
 
 class ForwardMessage private constructor(
     chatId: Long?,
diff --git a/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/JavaCompatabilityUtility.kt b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/JavaCompatabilityUtility.kt
new file mode 100644
index 00000000..89a70263
--- /dev/null
+++ b/library/src/main/java/com/pengrad/telegrambot/utility/kotlin/JavaCompatabilityUtility.kt
@@ -0,0 +1,7 @@
+@file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
+
+package com.pengrad.telegrambot.utility.kotlin
+
+typealias JavaInteger = java.lang.Integer
+
+typealias JavaLong = java.lang.Long
\ No newline at end of file

From c446c8a4084d2979d4a6d62abf5e6e7f6d9ea932 Mon Sep 17 00:00:00 2001
From: Andrew Anfanik <me@anfanik.me>
Date: Thu, 20 Feb 2025 00:20:55 +0300
Subject: [PATCH 18/18] Fix textParseMode method in SendGift

---
 .../src/main/java/com/pengrad/telegrambot/request/SendGift.kt   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/src/main/java/com/pengrad/telegrambot/request/SendGift.kt b/library/src/main/java/com/pengrad/telegrambot/request/SendGift.kt
index a783a19c..d581907d 100644
--- a/library/src/main/java/com/pengrad/telegrambot/request/SendGift.kt
+++ b/library/src/main/java/com/pengrad/telegrambot/request/SendGift.kt
@@ -78,7 +78,7 @@ class SendGift private constructor(
 
     fun text(text: String) = apply { this.text = text }
 
-    fun textParseMode(parseMode: ParseMode) = apply { this.textParseMode = textParseMode }
+    fun textParseMode(parseMode: ParseMode) = apply { this.textParseMode = parseMode }
 
     fun textEntities(textEntities: Array<MessageEntity>) = apply { this.textEntities = textEntities }