From e0e7768a03007e8e9c7f108e5bbdd65a20df691a Mon Sep 17 00:00:00 2001 From: ilopatin Date: Sun, 31 Dec 2023 13:27:09 +0100 Subject: [PATCH] Telegram Bot API December 29, 2023 updates (v7.0) --- .scalafmt.conf | 3 - README.md | 2 +- build.sbt | 2 +- .../telegramium/bots/CallbackQuery.scala | 5 +- .../main/scala/telegramium/bots/Chat.scala | 31 +- .../bots/ChatAdministratorRights.scala | 10 +- .../scala/telegramium/bots/ChatBoost.scala | 15 + .../telegramium/bots/ChatBoostRemoved.scala | 14 + .../telegramium/bots/ChatBoostSource.scala | 43 + .../telegramium/bots/ChatBoostUpdated.scala | 10 + .../telegramium/bots/ChatJoinRequest.scala | 2 +- .../scala/telegramium/bots/ChatMember.scala | 13 +- .../telegramium/bots/ChatPermissions.scala | 3 +- .../telegramium/bots/ExternalReplyInfo.scala | 78 + .../scala/telegramium/bots/Giveaway.scala | 33 + .../telegramium/bots/GiveawayCompleted.scala | 16 + .../telegramium/bots/GiveawayCreated.scala | 5 + .../telegramium/bots/GiveawayWinners.scala | 40 + .../bots/InputMessageContent.scala | 6 +- .../telegramium/bots/KeyboardButton.scala | 10 +- .../bots/KeyboardButtonRequestUser.scala | 20 - .../bots/KeyboardButtonRequestUsers.scala | 23 + .../telegramium/bots/LinkPreviewOptions.scala | 25 + ...e.scala => MaybeInaccessibleMessage.scala} | 79 +- .../telegramium/bots/MessageEntity.scala | 9 + .../telegramium/bots/MessageOrigin.scala | 64 + .../bots/MessageReactionCountUpdated.scala | 19 + .../bots/MessageReactionUpdated.scala | 28 + .../telegramium/bots/ReactionCount.scala | 10 + .../scala/telegramium/bots/ReactionType.scala | 25 + .../telegramium/bots/ReplyParameters.scala | 33 + .../scala/telegramium/bots/TextQuote.scala | 21 + .../main/scala/telegramium/bots/Update.scala | 20 +- .../telegramium/bots/UserChatBoosts.scala | 8 + .../scala/telegramium/bots/UserShared.scala | 14 - .../scala/telegramium/bots/UsersShared.scala | 15 + .../bots/client/CopyMessageReq.scala | 10 +- .../bots/client/CopyMessagesReq.scala | 30 + .../bots/client/DeleteMessagesReq.scala | 10 + .../bots/client/EditMessageTextReq.scala | 7 +- .../bots/client/ForwardMessagesReq.scala | 27 + .../bots/client/GetUpdatesReq.scala | 11 +- .../bots/client/GetUserChatBoostsReq.scala | 10 + .../telegramium/bots/client/Methods.scala | 474 ++--- .../bots/client/PromoteChatMemberReq.scala | 38 +- .../bots/client/SendAnimationReq.scala | 10 +- .../bots/client/SendAudioReq.scala | 10 +- .../bots/client/SendContactReq.scala | 10 +- .../telegramium/bots/client/SendDiceReq.scala | 10 +- .../bots/client/SendDocumentReq.scala | 10 +- .../telegramium/bots/client/SendGameReq.scala | 10 +- .../bots/client/SendInvoiceReq.scala | 10 +- .../bots/client/SendLocationReq.scala | 10 +- .../bots/client/SendMediaGroupReq.scala | 10 +- .../bots/client/SendMessageReq.scala | 17 +- .../bots/client/SendPhotoReq.scala | 10 +- .../telegramium/bots/client/SendPollReq.scala | 13 +- .../bots/client/SendStickerReq.scala | 10 +- .../bots/client/SendVenueReq.scala | 10 +- .../bots/client/SendVideoNoteReq.scala | 10 +- .../bots/client/SendVideoReq.scala | 10 +- .../bots/client/SendVoiceReq.scala | 10 +- .../bots/client/SetMessageReactionReq.scala | 22 + .../bots/client/SetWebhookReq.scala | 11 +- .../telegramium/bots/client/package.scala | 1063 ++++++------ .../main/scala/telegramium/bots/package.scala | 1535 +++++++++++++---- .../telegramium/bots/examples/EchoBot.scala | 18 +- .../bots/examples/IceCreamParlorBot.scala | 27 +- .../telegramium/bots/high/LongPollBot.scala | 36 +- .../telegramium/bots/high/WebhookBot.scala | 76 +- .../bots/high/keyboards/KeyboardButtons.scala | 6 +- .../messageentities/MessageEntities.scala | 1 + .../messageentities/MessageEntityFormat.scala | 6 + .../bots/high/LongPollBotISpec.scala | 60 +- .../bots/high/TestLongPollBot.scala | 34 +- .../bots/high/TestWebhookBot.scala | 28 + .../bots/high/WebhookBotISpec.scala | 57 +- .../messageentities/MessageEntitiesSpec.scala | 31 +- 78 files changed, 3158 insertions(+), 1404 deletions(-) create mode 100644 telegramium-core/src/main/scala/telegramium/bots/ChatBoost.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/ChatBoostRemoved.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/ChatBoostSource.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/ChatBoostUpdated.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/ExternalReplyInfo.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/Giveaway.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/GiveawayCompleted.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/GiveawayCreated.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/GiveawayWinners.scala delete mode 100644 telegramium-core/src/main/scala/telegramium/bots/KeyboardButtonRequestUser.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/KeyboardButtonRequestUsers.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/LinkPreviewOptions.scala rename telegramium-core/src/main/scala/telegramium/bots/{Message.scala => MaybeInaccessibleMessage.scala} (82%) create mode 100644 telegramium-core/src/main/scala/telegramium/bots/MessageOrigin.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/MessageReactionCountUpdated.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/MessageReactionUpdated.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/ReactionCount.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/ReactionType.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/ReplyParameters.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/TextQuote.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/UserChatBoosts.scala delete mode 100644 telegramium-core/src/main/scala/telegramium/bots/UserShared.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/UsersShared.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/client/CopyMessagesReq.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/client/DeleteMessagesReq.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/client/ForwardMessagesReq.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/client/GetUserChatBoostsReq.scala create mode 100644 telegramium-core/src/main/scala/telegramium/bots/client/SetMessageReactionReq.scala diff --git a/.scalafmt.conf b/.scalafmt.conf index 576cafaf..60b1b348 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -4,9 +4,6 @@ maxColumn = 120 continuationIndent.defnSite = 2 assumeStandardLibraryStripMargin = true danglingParentheses.preset = true -newlines.topLevelStatementBlankLines = [ - { blanks = 1 } -] runner.dialect = scala3 project.git = true project.excludePaths = [ diff --git a/README.md b/README.md index 0364392d..62ce8e3c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # F[Tg] - Telegramium -[![Telegram](https://img.shields.io/badge/Telegram%20Bot%20API-6.9%20(September%2022%2C%202023)-blue)](https://core.telegram.org/bots/api#recent-changes) +[![Telegram](https://img.shields.io/badge/Telegram%20Bot%20API-7.0%20(December%2029%2C%202023)-blue)](https://core.telegram.org/bots/api#recent-changes) [![Scala Steward badge](https://img.shields.io/badge/Scala_Steward-helping-blue.svg?style=flat&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAMAAAARSr4IAAAAVFBMVEUAAACHjojlOy5NWlrKzcYRKjGFjIbp293YycuLa3pYY2LSqql4f3pCUFTgSjNodYRmcXUsPD/NTTbjRS+2jomhgnzNc223cGvZS0HaSD0XLjbaSjElhIr+AAAAAXRSTlMAQObYZgAAAHlJREFUCNdNyosOwyAIhWHAQS1Vt7a77/3fcxxdmv0xwmckutAR1nkm4ggbyEcg/wWmlGLDAA3oL50xi6fk5ffZ3E2E3QfZDCcCN2YtbEWZt+Drc6u6rlqv7Uk0LdKqqr5rk2UCRXOk0vmQKGfc94nOJyQjouF9H/wCc9gECEYfONoAAAAASUVORK5CYII=)](https://scala-steward.org) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.github.apimorphism/telegramium-core_2.13/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.github.apimorphism/telegramium-core_2.13) diff --git a/build.sbt b/build.sbt index ef26131d..abd51cdf 100644 --- a/build.sbt +++ b/build.sbt @@ -1,7 +1,7 @@ enablePlugins(GitPlugin) ThisBuild / version := Version.mkVersion( - "8.69.0", + "8.70.0", git.gitCurrentBranch.value, git.gitDescribedVersion.value, git.gitUncommittedChanges.value diff --git a/telegramium-core/src/main/scala/telegramium/bots/CallbackQuery.scala b/telegramium-core/src/main/scala/telegramium/bots/CallbackQuery.scala index 5dbc0ef8..ec8f6bdf 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/CallbackQuery.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/CallbackQuery.scala @@ -13,8 +13,7 @@ package telegramium.bots * Global identifier, uniquely corresponding to the chat to which the message with the callback button was sent. * Useful for high scores in games. * @param message - * Optional. Message with the callback button that originated the query. Note that message content and message date - * will not be available if the message is too old + * Optional. Message sent by the bot with the callback button that originated the query * @param inlineMessageId * Optional. Identifier of the message sent via the bot in inline mode, that originated the query. * @param data @@ -27,7 +26,7 @@ final case class CallbackQuery( id: String, from: User, chatInstance: String, - message: Option[Message] = Option.empty, + message: Option[MaybeInaccessibleMessage] = Option.empty, inlineMessageId: Option[String] = Option.empty, data: Option[String] = Option.empty, gameShortName: Option[String] = Option.empty diff --git a/telegramium-core/src/main/scala/telegramium/bots/Chat.scala b/telegramium-core/src/main/scala/telegramium/bots/Chat.scala index 84be3d79..a94f5294 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/Chat.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/Chat.scala @@ -23,11 +23,27 @@ package telegramium.bots * @param activeUsernames * Optional. If non-empty, the list of all active chat usernames; for private chats, supergroups and channels. * Returned only in getChat. + * @param availableReactions + * Optional. List of available reactions allowed in the chat. If omitted, then all emoji reactions are allowed. + * Returned only in getChat. + * @param accentColorId + * Optional. Identifier of the accent color for the chat name and backgrounds of the chat photo, reply header, and + * link preview. See accent colors for more details. Returned only in getChat. Always returned in getChat. + * @param backgroundCustomEmojiId + * Optional. Custom emoji identifier of emoji chosen by the chat for the reply header and link preview background. + * Returned only in getChat. + * @param profileAccentColorId + * Optional. Identifier of the accent color for the chat's profile background. See profile accent colors for more + * details. Returned only in getChat. + * @param profileBackgroundCustomEmojiId + * Optional. Custom emoji identifier of the emoji chosen by the chat for its profile background. Returned only in + * getChat. * @param emojiStatusCustomEmojiId - * Optional. Custom emoji identifier of emoji status of the other party in a private chat. Returned only in getChat. - * @param emojiStatusExpirationDate - * Optional. Expiration date of the emoji status of the other party in a private chat in Unix time, if any. Returned + * Optional. Custom emoji identifier of the emoji status of the chat or the other party in a private chat. Returned * only in getChat. + * @param emojiStatusExpirationDate + * Optional. Expiration date of the emoji status of the chat or the other party in a private chat, in Unix time, if + * any. Returned only in getChat. * @param bio * Optional. Bio of the other party in a private chat. Returned only in getChat. * @param hasPrivateForwards @@ -63,6 +79,9 @@ package telegramium.bots * in getChat. * @param hasProtectedContent * Optional. True, if messages from the chat can't be forwarded to other chats. Returned only in getChat. + * @param hasVisibleHistory + * Optional. True, if new chat members will have access to old messages; available only to chat administrators. + * Returned only in getChat. * @param stickerSetName * Optional. For supergroups, name of group sticker set. Returned only in getChat. * @param canSetStickerSet @@ -85,6 +104,11 @@ final case class Chat( isForum: Option[Boolean] = Option.empty, photo: Option[ChatPhoto] = Option.empty, activeUsernames: List[String] = List.empty, + availableReactions: List[ReactionType] = List.empty, + accentColorId: Option[Int] = Option.empty, + backgroundCustomEmojiId: Option[String] = Option.empty, + profileAccentColorId: Option[Int] = Option.empty, + profileBackgroundCustomEmojiId: Option[String] = Option.empty, emojiStatusCustomEmojiId: Option[String] = Option.empty, emojiStatusExpirationDate: Option[Int] = Option.empty, bio: Option[String] = Option.empty, @@ -101,6 +125,7 @@ final case class Chat( hasAggressiveAntiSpamEnabled: Option[Boolean] = Option.empty, hasHiddenMembers: Option[Boolean] = Option.empty, hasProtectedContent: Option[Boolean] = Option.empty, + hasVisibleHistory: Option[Boolean] = Option.empty, stickerSetName: Option[String] = Option.empty, canSetStickerSet: Option[Boolean] = Option.empty, linkedChatId: Option[Long] = Option.empty, diff --git a/telegramium-core/src/main/scala/telegramium/bots/ChatAdministratorRights.scala b/telegramium-core/src/main/scala/telegramium/bots/ChatAdministratorRights.scala index 85541d60..2eaaa02a 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/ChatAdministratorRights.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/ChatAdministratorRights.scala @@ -5,15 +5,15 @@ package telegramium.bots * @param isAnonymous * True, if the user's presence in the chat is hidden * @param canManageChat - * True, if the administrator can access the chat event log, chat statistics, boost list in channels, message - * statistics in channels, see channel members, see anonymous administrators in supergroups and ignore slow mode. - * Implied by any other administrator privilege + * True, if the administrator can access the chat event log, boost list in channels, see channel members, report spam + * messages, see anonymous administrators in supergroups and ignore slow mode. Implied by any other administrator + * privilege * @param canDeleteMessages * True, if the administrator can delete messages of other users * @param canManageVideoChats * True, if the administrator can manage video chats * @param canRestrictMembers - * True, if the administrator can restrict, ban or unban chat members + * True, if the administrator can restrict, ban or unban chat members, or access supergroup statistics * @param canPromoteMembers * True, if the administrator can add new administrators with a subset of their own privileges or demote * administrators that they have promoted, directly or indirectly (promoted by administrators that were appointed by @@ -23,7 +23,7 @@ package telegramium.bots * @param canInviteUsers * True, if the user is allowed to invite new users to the chat * @param canPostMessages - * Optional. True, if the administrator can post messages in the channel; channels only + * Optional. True, if the administrator can post messages in the channel, or access channel statistics; channels only * @param canEditMessages * Optional. True, if the administrator can edit messages of other users and can pin messages; channels only * @param canPinMessages diff --git a/telegramium-core/src/main/scala/telegramium/bots/ChatBoost.scala b/telegramium-core/src/main/scala/telegramium/bots/ChatBoost.scala new file mode 100644 index 00000000..1ca9cc17 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/ChatBoost.scala @@ -0,0 +1,15 @@ +package telegramium.bots + +/** This object contains information about a chat boost. + * + * @param boostId + * Unique identifier of the boost + * @param addDate + * Point in time (Unix timestamp) when the chat was boosted + * @param expirationDate + * Point in time (Unix timestamp) when the boost will automatically expire, unless the booster's Telegram Premium + * subscription is prolonged + * @param source + * Source of the added boost + */ +final case class ChatBoost(boostId: String, addDate: Int, expirationDate: Int, source: ChatBoostSource) diff --git a/telegramium-core/src/main/scala/telegramium/bots/ChatBoostRemoved.scala b/telegramium-core/src/main/scala/telegramium/bots/ChatBoostRemoved.scala new file mode 100644 index 00000000..f59423d1 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/ChatBoostRemoved.scala @@ -0,0 +1,14 @@ +package telegramium.bots + +/** This object represents a boost removed from a chat. + * + * @param chat + * Chat which was boosted + * @param boostId + * Unique identifier of the boost + * @param removeDate + * Point in time (Unix timestamp) when the boost was removed + * @param source + * Source of the removed boost + */ +final case class ChatBoostRemoved(chat: Chat, boostId: String, removeDate: Int, source: ChatBoostSource) diff --git a/telegramium-core/src/main/scala/telegramium/bots/ChatBoostSource.scala b/telegramium-core/src/main/scala/telegramium/bots/ChatBoostSource.scala new file mode 100644 index 00000000..27cecefb --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/ChatBoostSource.scala @@ -0,0 +1,43 @@ +package telegramium.bots + +sealed trait ChatBoostSource {} + +/** The boost was obtained by the creation of Telegram Premium gift codes to boost a chat. Each such code boosts the + * chat 4 times for the duration of the corresponding Telegram Premium subscription. + * + * @param source + * Source of the boost, always “gift_code” + * @param user + * User for which the gift code was created + */ +final case class ChatBoostSourceGiftCode(source: String, user: User) extends ChatBoostSource + +/** The boost was obtained by the creation of a Telegram Premium giveaway. This boosts the chat 4 times for the duration + * of the corresponding Telegram Premium subscription. + * + * @param source + * Source of the boost, always “giveaway” + * @param giveawayMessageId + * Identifier of a message in the chat with the giveaway; the message could have been deleted already. May be 0 if + * the message isn't sent yet. + * @param user + * Optional. User that won the prize in the giveaway if any + * @param isUnclaimed + * Optional. True, if the giveaway was completed, but there was no user to win the prize + */ +final case class ChatBoostSourceGiveaway( + source: String, + giveawayMessageId: Int, + user: Option[User] = Option.empty, + isUnclaimed: Option[Boolean] = Option.empty +) extends ChatBoostSource + +/** The boost was obtained by subscribing to Telegram Premium or by gifting a Telegram Premium subscription to another + * user. + * + * @param source + * Source of the boost, always “premium” + * @param user + * User that boosted the chat + */ +final case class ChatBoostSourcePremium(source: String, user: User) extends ChatBoostSource diff --git a/telegramium-core/src/main/scala/telegramium/bots/ChatBoostUpdated.scala b/telegramium-core/src/main/scala/telegramium/bots/ChatBoostUpdated.scala new file mode 100644 index 00000000..4451d55c --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/ChatBoostUpdated.scala @@ -0,0 +1,10 @@ +package telegramium.bots + +/** This object represents a boost added to a chat or changed. + * + * @param chat + * Chat which was boosted + * @param boost + * Infomation about the chat boost + */ +final case class ChatBoostUpdated(chat: Chat, boost: ChatBoost) diff --git a/telegramium-core/src/main/scala/telegramium/bots/ChatJoinRequest.scala b/telegramium-core/src/main/scala/telegramium/bots/ChatJoinRequest.scala index 5a1cfc25..1db40558 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/ChatJoinRequest.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/ChatJoinRequest.scala @@ -10,7 +10,7 @@ package telegramium.bots * Identifier of a private chat with the user who sent the join request. This number may have more than 32 * significant bits and some programming languages may have difficulty/silent defects in interpreting it. But it has * at most 52 significant bits, so a 64-bit integer or double-precision float type are safe for storing this - * identifier. The bot can use this identifier for 24 hours to send messages until the join request is processed, + * identifier. The bot can use this identifier for 5 minutes to send messages until the join request is processed, * assuming no other administrator contacted the user. * @param date * Date the request was sent in Unix time diff --git a/telegramium-core/src/main/scala/telegramium/bots/ChatMember.scala b/telegramium-core/src/main/scala/telegramium/bots/ChatMember.scala index 8f102fd1..70c04ec5 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/ChatMember.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/ChatMember.scala @@ -31,15 +31,15 @@ final case class ChatMemberOwner( * @param isAnonymous * True, if the user's presence in the chat is hidden * @param canManageChat - * True, if the administrator can access the chat event log, chat statistics, boost list in channels, message - * statistics in channels, see channel members, see anonymous administrators in supergroups and ignore slow mode. - * Implied by any other administrator privilege + * True, if the administrator can access the chat event log, boost list in channels, see channel members, report spam + * messages, see anonymous administrators in supergroups and ignore slow mode. Implied by any other administrator + * privilege * @param canDeleteMessages * True, if the administrator can delete messages of other users * @param canManageVideoChats * True, if the administrator can manage video chats * @param canRestrictMembers - * True, if the administrator can restrict, ban or unban chat members + * True, if the administrator can restrict, ban or unban chat members, or access supergroup statistics * @param canPromoteMembers * True, if the administrator can add new administrators with a subset of their own privileges or demote * administrators that they have promoted, directly or indirectly (promoted by administrators that were appointed by @@ -49,7 +49,7 @@ final case class ChatMemberOwner( * @param canInviteUsers * True, if the user is allowed to invite new users to the chat * @param canPostMessages - * Optional. True, if the administrator can post messages in the channel; channels only + * Optional. True, if the administrator can post messages in the channel, or access channel statistics; channels only * @param canEditMessages * Optional. True, if the administrator can edit messages of other users and can pin messages; channels only * @param canPinMessages @@ -125,7 +125,8 @@ final case class ChatMemberBanned(status: String, user: User, untilDate: Int) ex * @param isMember * True, if the user is a member of the chat at the moment of the request * @param canSendMessages - * True, if the user is allowed to send text messages, contacts, invoices, locations and venues + * True, if the user is allowed to send text messages, contacts, giveaways, giveaway winners, invoices, locations and + * venues * @param canSendAudios * True, if the user is allowed to send audios * @param canSendDocuments diff --git a/telegramium-core/src/main/scala/telegramium/bots/ChatPermissions.scala b/telegramium-core/src/main/scala/telegramium/bots/ChatPermissions.scala index 9f8228cf..938cf4ce 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/ChatPermissions.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/ChatPermissions.scala @@ -3,7 +3,8 @@ package telegramium.bots /** Describes actions that a non-administrator user is allowed to take in a chat. * * @param canSendMessages - * Optional. True, if the user is allowed to send text messages, contacts, invoices, locations and venues + * Optional. True, if the user is allowed to send text messages, contacts, giveaways, giveaway winners, invoices, + * locations and venues * @param canSendAudios * Optional. True, if the user is allowed to send audios * @param canSendDocuments diff --git a/telegramium-core/src/main/scala/telegramium/bots/ExternalReplyInfo.scala b/telegramium-core/src/main/scala/telegramium/bots/ExternalReplyInfo.scala new file mode 100644 index 00000000..50491bf1 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/ExternalReplyInfo.scala @@ -0,0 +1,78 @@ +package telegramium.bots + +/** This object contains information about a message that is being replied to, which may come from another chat or forum + * topic. + * + * @param origin + * Origin of the message replied to by the given message + * @param chat + * Optional. Chat the original message belongs to. Available only if the chat is a supergroup or a channel. + * @param messageId + * Optional. Unique message identifier inside the original chat. Available only if the original chat is a supergroup + * or a channel. + * @param linkPreviewOptions + * Optional. Options used for link preview generation for the original message, if it is a text message + * @param animation + * Optional. Message is an animation, information about the animation + * @param audio + * Optional. Message is an audio file, information about the file + * @param document + * Optional. Message is a general file, information about the file + * @param photo + * Optional. Message is a photo, available sizes of the photo + * @param sticker + * Optional. Message is a sticker, information about the sticker + * @param story + * Optional. Message is a forwarded story + * @param video + * Optional. Message is a video, information about the video + * @param videoNote + * Optional. Message is a video note, information about the video message + * @param voice + * Optional. Message is a voice message, information about the file + * @param hasMediaSpoiler + * Optional. True, if the message media is covered by a spoiler animation + * @param contact + * Optional. Message is a shared contact, information about the contact + * @param dice + * Optional. Message is a dice with random value + * @param game + * Optional. Message is a game, information about the game. + * @param giveaway + * Optional. Message is a scheduled giveaway, information about the giveaway + * @param giveawayWinners + * Optional. A giveaway with public winners was completed + * @param invoice + * Optional. Message is an invoice for a payment, information about the invoice. + * @param location + * Optional. Message is a shared location, information about the location + * @param poll + * Optional. Message is a native poll, information about the poll + * @param venue + * Optional. Message is a venue, information about the venue + */ +final case class ExternalReplyInfo( + origin: MessageOrigin, + chat: Option[Chat] = Option.empty, + messageId: Option[Int] = Option.empty, + linkPreviewOptions: Option[LinkPreviewOptions] = Option.empty, + animation: Option[Animation] = Option.empty, + audio: Option[Audio] = Option.empty, + document: Option[Document] = Option.empty, + photo: List[PhotoSize] = List.empty, + sticker: Option[Sticker] = Option.empty, + story: Option[Story.type] = Option.empty, + video: Option[Video] = Option.empty, + videoNote: Option[VideoNote] = Option.empty, + voice: Option[Voice] = Option.empty, + hasMediaSpoiler: Option[Boolean] = Option.empty, + contact: Option[Contact] = Option.empty, + dice: Option[Dice] = Option.empty, + game: Option[Game] = Option.empty, + giveaway: Option[Giveaway] = Option.empty, + giveawayWinners: Option[GiveawayWinners] = Option.empty, + invoice: Option[Invoice] = Option.empty, + location: Option[Location] = Option.empty, + poll: Option[Poll] = Option.empty, + venue: Option[Venue] = Option.empty +) diff --git a/telegramium-core/src/main/scala/telegramium/bots/Giveaway.scala b/telegramium-core/src/main/scala/telegramium/bots/Giveaway.scala new file mode 100644 index 00000000..442e04ea --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/Giveaway.scala @@ -0,0 +1,33 @@ +package telegramium.bots + +/** This object represents a message about a scheduled giveaway. + * + * @param winnersSelectionDate + * Point in time (Unix timestamp) when winners of the giveaway will be selected + * @param winnerCount + * The number of users which are supposed to be selected as winners of the giveaway + * @param chats + * The list of chats which the user must join to participate in the giveaway + * @param onlyNewMembers + * Optional. True, if only users who join the chats after the giveaway started should be eligible to win + * @param hasPublicWinners + * Optional. True, if the list of giveaway winners will be visible to everyone + * @param prizeDescription + * Optional. Description of additional giveaway prize + * @param countryCodes + * Optional. A list of two-letter ISO 3166-1 alpha-2 country codes indicating the countries from which eligible users + * for the giveaway must come. If empty, then all users can participate in the giveaway. Users with a phone number + * that was bought on Fragment can always participate in giveaways. + * @param premiumSubscriptionMonthCount + * Optional. The number of months the Telegram Premium subscription won from the giveaway will be active for + */ +final case class Giveaway( + winnersSelectionDate: Int, + winnerCount: Int, + chats: List[Chat] = List.empty, + onlyNewMembers: Option[Boolean] = Option.empty, + hasPublicWinners: Option[Boolean] = Option.empty, + prizeDescription: Option[String] = Option.empty, + countryCodes: List[String] = List.empty, + premiumSubscriptionMonthCount: Option[Int] = Option.empty +) diff --git a/telegramium-core/src/main/scala/telegramium/bots/GiveawayCompleted.scala b/telegramium-core/src/main/scala/telegramium/bots/GiveawayCompleted.scala new file mode 100644 index 00000000..e9bacda1 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/GiveawayCompleted.scala @@ -0,0 +1,16 @@ +package telegramium.bots + +/** This object represents a service message about the completion of a giveaway without public winners. + * + * @param winnerCount + * Number of winners in the giveaway + * @param unclaimedPrizeCount + * Optional. Number of undistributed prizes + * @param giveawayMessage + * Optional. Message with the giveaway that was completed, if it wasn't deleted + */ +final case class GiveawayCompleted( + winnerCount: Int, + unclaimedPrizeCount: Option[Int] = Option.empty, + giveawayMessage: Option[Message] = Option.empty +) diff --git a/telegramium-core/src/main/scala/telegramium/bots/GiveawayCreated.scala b/telegramium-core/src/main/scala/telegramium/bots/GiveawayCreated.scala new file mode 100644 index 00000000..760b3e90 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/GiveawayCreated.scala @@ -0,0 +1,5 @@ +package telegramium.bots + +/** This object represents a service message about the creation of a scheduled giveaway. Currently holds no information. + */ +case object GiveawayCreated diff --git a/telegramium-core/src/main/scala/telegramium/bots/GiveawayWinners.scala b/telegramium-core/src/main/scala/telegramium/bots/GiveawayWinners.scala new file mode 100644 index 00000000..a299e76d --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/GiveawayWinners.scala @@ -0,0 +1,40 @@ +package telegramium.bots + +/** This object represents a message about the completion of a giveaway with public winners. + * + * @param chat + * The chat that created the giveaway + * @param giveawayMessageId + * Identifier of the messsage with the giveaway in the chat + * @param winnersSelectionDate + * Point in time (Unix timestamp) when winners of the giveaway were selected + * @param winnerCount + * Total number of winners in the giveaway + * @param winners + * List of up to 100 winners of the giveaway + * @param additionalChatCount + * Optional. The number of other chats the user had to join in order to be eligible for the giveaway + * @param premiumSubscriptionMonthCount + * Optional. The number of months the Telegram Premium subscription won from the giveaway will be active for + * @param unclaimedPrizeCount + * Optional. Number of undistributed prizes + * @param onlyNewMembers + * Optional. True, if only users who had joined the chats after the giveaway started were eligible to win + * @param wasRefunded + * Optional. True, if the giveaway was canceled because the payment for it was refunded + * @param prizeDescription + * Optional. Description of additional giveaway prize + */ +final case class GiveawayWinners( + chat: Chat, + giveawayMessageId: Int, + winnersSelectionDate: Int, + winnerCount: Int, + winners: List[User] = List.empty, + additionalChatCount: Option[Int] = Option.empty, + premiumSubscriptionMonthCount: Option[Int] = Option.empty, + unclaimedPrizeCount: Option[Int] = Option.empty, + onlyNewMembers: Option[Boolean] = Option.empty, + wasRefunded: Option[Boolean] = Option.empty, + prizeDescription: Option[String] = Option.empty +) diff --git a/telegramium-core/src/main/scala/telegramium/bots/InputMessageContent.scala b/telegramium-core/src/main/scala/telegramium/bots/InputMessageContent.scala index 634d5096..b412318c 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/InputMessageContent.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/InputMessageContent.scala @@ -159,12 +159,12 @@ final case class InputLocationMessageContent( * Optional. Mode for parsing entities in the message text. See formatting options for more details. * @param entities * Optional. List of special entities that appear in message text, which can be specified instead of parse_mode - * @param disableWebPagePreview - * Optional. Disables link previews for links in the sent message + * @param linkPreviewOptions + * Optional. Link preview generation options for the message */ final case class InputTextMessageContent( messageText: String, parseMode: Option[ParseMode] = Option.empty, entities: List[MessageEntity] = List.empty, - disableWebPagePreview: Option[Boolean] = Option.empty + linkPreviewOptions: Option[LinkPreviewOptions] = Option.empty ) extends InputMessageContent diff --git a/telegramium-core/src/main/scala/telegramium/bots/KeyboardButton.scala b/telegramium-core/src/main/scala/telegramium/bots/KeyboardButton.scala index 2b298ec7..2d575fea 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/KeyboardButton.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/KeyboardButton.scala @@ -1,15 +1,15 @@ package telegramium.bots /** This object represents one button of the reply keyboard. For simple text buttons, String can be used instead of this - * object to specify the button text. The optional fields web_app, request_user, request_chat, request_contact, + * object to specify the button text. The optional fields web_app, request_users, request_chat, request_contact, * request_location, and request_poll are mutually exclusive. * * @param text * Text of the button. If none of the optional fields are used, it will be sent as a message when the button is * pressed - * @param requestUser - * Optional. If specified, pressing the button will open a list of suitable users. Tapping on any user will send - * their identifier to the bot in a “user_shared” service message. Available in private chats only. + * @param requestUsers + * Optional. If specified, pressing the button will open a list of suitable users. Identifiers of selected users will + * be sent to the bot in a “users_shared” service message. Available in private chats only. * @param requestChat * Optional. If specified, pressing the button will open a list of suitable chats. Tapping on a chat will send its * identifier to the bot in a “chat_shared” service message. Available in private chats only. @@ -28,7 +28,7 @@ package telegramium.bots */ final case class KeyboardButton( text: String, - requestUser: Option[KeyboardButtonRequestUser] = Option.empty, + requestUsers: Option[KeyboardButtonRequestUsers] = Option.empty, requestChat: Option[KeyboardButtonRequestChat] = Option.empty, requestContact: Option[Boolean] = Option.empty, requestLocation: Option[Boolean] = Option.empty, diff --git a/telegramium-core/src/main/scala/telegramium/bots/KeyboardButtonRequestUser.scala b/telegramium-core/src/main/scala/telegramium/bots/KeyboardButtonRequestUser.scala deleted file mode 100644 index 7c02bec7..00000000 --- a/telegramium-core/src/main/scala/telegramium/bots/KeyboardButtonRequestUser.scala +++ /dev/null @@ -1,20 +0,0 @@ -package telegramium.bots - -/** This object defines the criteria used to request a suitable user. The identifier of the selected user will be shared - * with the bot when the corresponding button is pressed. - * - * @param requestId - * Signed 32-bit identifier of the request, which will be received back in the UserShared object. Must be unique - * within the message - * @param userIsBot - * Optional. Pass True to request a bot, pass False to request a regular user. If not specified, no additional - * restrictions are applied. - * @param userIsPremium - * Optional. Pass True to request a premium user, pass False to request a non-premium user. If not specified, no - * additional restrictions are applied. - */ -final case class KeyboardButtonRequestUser( - requestId: Int, - userIsBot: Option[Boolean] = Option.empty, - userIsPremium: Option[Boolean] = Option.empty -) diff --git a/telegramium-core/src/main/scala/telegramium/bots/KeyboardButtonRequestUsers.scala b/telegramium-core/src/main/scala/telegramium/bots/KeyboardButtonRequestUsers.scala new file mode 100644 index 00000000..f2a956c0 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/KeyboardButtonRequestUsers.scala @@ -0,0 +1,23 @@ +package telegramium.bots + +/** This object defines the criteria used to request suitable users. The identifiers of the selected users will be + * shared with the bot when the corresponding button is pressed. + * + * @param requestId + * Signed 32-bit identifier of the request that will be received back in the UsersShared object. Must be unique + * within the message + * @param userIsBot + * Optional. Pass True to request bots, pass False to request regular users. If not specified, no additional + * restrictions are applied. + * @param userIsPremium + * Optional. Pass True to request premium users, pass False to request non-premium users. If not specified, no + * additional restrictions are applied. + * @param maxQuantity + * Optional. The maximum number of users to be selected; 1-10. Defaults to 1. + */ +final case class KeyboardButtonRequestUsers( + requestId: Int, + userIsBot: Option[Boolean] = Option.empty, + userIsPremium: Option[Boolean] = Option.empty, + maxQuantity: Option[Int] = Option.empty +) diff --git a/telegramium-core/src/main/scala/telegramium/bots/LinkPreviewOptions.scala b/telegramium-core/src/main/scala/telegramium/bots/LinkPreviewOptions.scala new file mode 100644 index 00000000..67463522 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/LinkPreviewOptions.scala @@ -0,0 +1,25 @@ +package telegramium.bots + +/** Describes the options used for link preview generation. + * + * @param isDisabled + * Optional. True, if the link preview is disabled + * @param url + * Optional. URL to use for the link preview. If empty, then the first URL found in the message text will be used + * @param preferSmallMedia + * Optional. True, if the media in the link preview is suppposed to be shrunk; ignored if the URL isn't explicitly + * specified or media size change isn't supported for the preview + * @param preferLargeMedia + * Optional. True, if the media in the link preview is suppposed to be enlarged; ignored if the URL isn't explicitly + * specified or media size change isn't supported for the preview + * @param showAboveText + * Optional. True, if the link preview must be shown above the message text; otherwise, the link preview will be + * shown below the message text + */ +final case class LinkPreviewOptions( + isDisabled: Option[Boolean] = Option.empty, + url: Option[String] = Option.empty, + preferSmallMedia: Option[Boolean] = Option.empty, + preferLargeMedia: Option[Boolean] = Option.empty, + showAboveText: Option[Boolean] = Option.empty +) diff --git a/telegramium-core/src/main/scala/telegramium/bots/Message.scala b/telegramium-core/src/main/scala/telegramium/bots/MaybeInaccessibleMessage.scala similarity index 82% rename from telegramium-core/src/main/scala/telegramium/bots/Message.scala rename to telegramium-core/src/main/scala/telegramium/bots/MaybeInaccessibleMessage.scala index 987eb536..382a6a3b 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/Message.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/MaybeInaccessibleMessage.scala @@ -1,13 +1,15 @@ package telegramium.bots +sealed trait MaybeInaccessibleMessage {} + /** This object represents a message. * * @param messageId * Unique message identifier inside this chat * @param date - * Date the message was sent in Unix time + * Date the message was sent in Unix time. It is always a positive number, representing a valid date. * @param chat - * Conversation the message belongs to + * Chat the message belongs to * @param messageThreadId * Optional. Unique identifier of a message thread to which the message belongs; for supergroups only * @param from @@ -18,29 +20,20 @@ package telegramium.bots * supergroup itself for messages from anonymous group administrators, the linked channel for messages automatically * forwarded to the discussion group. For backward compatibility, the field from contains a fake sender user in * non-channel chats, if the message was sent on behalf of a chat. - * @param forwardFrom - * Optional. For forwarded messages, sender of the original message - * @param forwardFromChat - * Optional. For messages forwarded from channels or from anonymous administrators, information about the original - * sender chat - * @param forwardFromMessageId - * Optional. For messages forwarded from channels, identifier of the original message in the channel - * @param forwardSignature - * Optional. For forwarded messages that were originally sent in channels or by an anonymous chat administrator, - * signature of the message sender if present - * @param forwardSenderName - * Optional. Sender's name for messages forwarded from users who disallow adding a link to their account in forwarded - * messages - * @param forwardDate - * Optional. For forwarded messages, date the original message was sent in Unix time + * @param forwardOrigin + * Optional. Information about the original message for forwarded messages * @param isTopicMessage * Optional. True, if the message is sent to a forum topic * @param isAutomaticForward * Optional. True, if the message is a channel post that was automatically forwarded to the connected discussion * group * @param replyToMessage - * Optional. For replies, the original message. Note that the Message object in this field will not contain further - * reply_to_message fields even if it itself is a reply. + * Optional. For replies in the same chat and message thread, the original message. Note that the Message object in + * this field will not contain further reply_to_message fields even if it itself is a reply. + * @param externalReply + * Optional. Information about the message that is being replied to, which may come from another chat or forum topic + * @param quote + * Optional. For replies that quote part of the original message, the quoted part of the message * @param viaBot * Optional. Bot through which the message was sent * @param editDate @@ -56,6 +49,9 @@ package telegramium.bots * Optional. For text messages, the actual UTF-8 text of the message * @param entities * Optional. For text messages, special entities like usernames, URLs, bot commands, etc. that appear in the text + * @param linkPreviewOptions + * Optional. Options used for link preview generation for the message, if it is a text message and link preview + * options were changed * @param animation * Optional. Message is an animation, information about the animation. For backward compatibility, when this field is * set, the document field will also be set @@ -130,13 +126,13 @@ package telegramium.bots * this identifier. * @param pinnedMessage * Optional. Specified message was pinned. Note that the Message object in this field will not contain further - * reply_to_message fields even if it is itself a reply. + * reply_to_message fields even if it itself is a reply. * @param invoice * Optional. Message is an invoice for a payment, information about the invoice. * @param successfulPayment * Optional. Message is a service message about a successful payment, information about the payment. - * @param userShared - * Optional. Service message: a user was shared with the bot + * @param usersShared + * Optional. Service message: users were shared with the bot * @param chatShared * Optional. Service message: a chat was shared with the bot * @param connectedWebsite @@ -162,6 +158,14 @@ package telegramium.bots * Optional. Service message: the 'General' forum topic hidden * @param generalForumTopicUnhidden * Optional. Service message: the 'General' forum topic unhidden + * @param giveawayCreated + * Optional. Service message: a scheduled giveaway was created + * @param giveaway + * Optional. The message is a scheduled giveaway message + * @param giveawayWinners + * Optional. A giveaway with public winners was completed + * @param giveawayCompleted + * Optional. Service message: a giveaway without public winners was completed * @param videoChatScheduled * Optional. Service message: video chat scheduled * @param videoChatStarted @@ -182,15 +186,12 @@ final case class Message( messageThreadId: Option[Int] = Option.empty, from: Option[User] = Option.empty, senderChat: Option[Chat] = Option.empty, - forwardFrom: Option[User] = Option.empty, - forwardFromChat: Option[Chat] = Option.empty, - forwardFromMessageId: Option[Int] = Option.empty, - forwardSignature: Option[String] = Option.empty, - forwardSenderName: Option[String] = Option.empty, - forwardDate: Option[Int] = Option.empty, + forwardOrigin: Option[MessageOrigin] = Option.empty, isTopicMessage: Option[Boolean] = Option.empty, isAutomaticForward: Option[Boolean] = Option.empty, replyToMessage: Option[Message] = Option.empty, + externalReply: Option[ExternalReplyInfo] = Option.empty, + quote: Option[TextQuote] = Option.empty, viaBot: Option[User] = Option.empty, editDate: Option[Int] = Option.empty, hasProtectedContent: Option[Boolean] = Option.empty, @@ -198,6 +199,7 @@ final case class Message( authorSignature: Option[String] = Option.empty, text: Option[String] = Option.empty, entities: List[MessageEntity] = List.empty, + linkPreviewOptions: Option[LinkPreviewOptions] = Option.empty, animation: Option[Animation] = Option.empty, audio: Option[Audio] = Option.empty, document: Option[Document] = Option.empty, @@ -227,10 +229,10 @@ final case class Message( messageAutoDeleteTimerChanged: Option[MessageAutoDeleteTimerChanged] = Option.empty, migrateToChatId: Option[Long] = Option.empty, migrateFromChatId: Option[Long] = Option.empty, - pinnedMessage: Option[Message] = Option.empty, + pinnedMessage: Option[MaybeInaccessibleMessage] = Option.empty, invoice: Option[Invoice] = Option.empty, successfulPayment: Option[SuccessfulPayment] = Option.empty, - userShared: Option[UserShared] = Option.empty, + usersShared: Option[UsersShared] = Option.empty, chatShared: Option[ChatShared] = Option.empty, connectedWebsite: Option[String] = Option.empty, writeAccessAllowed: Option[WriteAccessAllowed] = Option.empty, @@ -242,10 +244,25 @@ final case class Message( forumTopicReopened: Option[ForumTopicReopened.type] = Option.empty, generalForumTopicHidden: Option[GeneralForumTopicHidden.type] = Option.empty, generalForumTopicUnhidden: Option[GeneralForumTopicUnhidden.type] = Option.empty, + giveawayCreated: Option[GiveawayCreated.type] = Option.empty, + giveaway: Option[Giveaway] = Option.empty, + giveawayWinners: Option[GiveawayWinners] = Option.empty, + giveawayCompleted: Option[GiveawayCompleted] = Option.empty, videoChatScheduled: Option[VideoChatScheduled] = Option.empty, videoChatStarted: Option[VideoChatStarted.type] = Option.empty, videoChatEnded: Option[VideoChatEnded] = Option.empty, videoChatParticipantsInvited: Option[VideoChatParticipantsInvited] = Option.empty, webAppData: Option[WebAppData] = Option.empty, replyMarkup: Option[InlineKeyboardMarkup] = Option.empty -) +) extends MaybeInaccessibleMessage + +/** This object describes a message that was deleted or is otherwise inaccessible to the bot. + * + * @param chat + * Chat the message belonged to + * @param messageId + * Unique message identifier inside the chat + * @param date + * Always 0. The field can be used to differentiate regular and inaccessible messages. + */ +final case class InaccessibleMessage(chat: Chat, messageId: Int, date: Int) extends MaybeInaccessibleMessage diff --git a/telegramium-core/src/main/scala/telegramium/bots/MessageEntity.scala b/telegramium-core/src/main/scala/telegramium/bots/MessageEntity.scala index a5dcaaf2..c64ae9b2 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/MessageEntity.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/MessageEntity.scala @@ -74,6 +74,15 @@ final case class SpoilerMessageEntity(offset: Int, length: Int) extends MessageE */ final case class EmailMessageEntity(offset: Int, length: Int) extends MessageEntity +/** blockquote + * + * @param offset + * Offset in UTF-16 code units to the start of the entity + * @param length + * Length of the entity in UTF-16 code units + */ +final case class BlockquoteMessageEntity(offset: Int, length: Int) extends MessageEntity + /** bold * * @param offset diff --git a/telegramium-core/src/main/scala/telegramium/bots/MessageOrigin.scala b/telegramium-core/src/main/scala/telegramium/bots/MessageOrigin.scala new file mode 100644 index 00000000..c3fbedff --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/MessageOrigin.scala @@ -0,0 +1,64 @@ +package telegramium.bots + +sealed trait MessageOrigin {} + +/** The message was originally sent by a known user. + * + * @param type + * Type of the message origin, always “user” + * @param date + * Date the message was sent originally in Unix time + * @param senderUser + * User that sent the message originally + */ +final case class MessageOriginUser(`type`: String, date: Int, senderUser: User) extends MessageOrigin + +/** The message was originally sent to a channel chat. + * + * @param type + * Type of the message origin, always “channel” + * @param date + * Date the message was sent originally in Unix time + * @param chat + * Channel chat to which the message was originally sent + * @param messageId + * Unique message identifier inside the chat + * @param authorSignature + * Optional. Signature of the original post author + */ +final case class MessageOriginChannel( + `type`: String, + date: Int, + chat: Chat, + messageId: Int, + authorSignature: Option[String] = Option.empty +) extends MessageOrigin + +/** The message was originally sent by an unknown user. + * + * @param type + * Type of the message origin, always “hidden_user” + * @param date + * Date the message was sent originally in Unix time + * @param senderUserName + * Name of the user that sent the message originally + */ +final case class MessageOriginHiddenUser(`type`: String, date: Int, senderUserName: String) extends MessageOrigin + +/** The message was originally sent on behalf of a chat to a group chat. + * + * @param type + * Type of the message origin, always “chat” + * @param date + * Date the message was sent originally in Unix time + * @param senderChat + * Chat that sent the message originally + * @param authorSignature + * Optional. For messages originally sent by an anonymous chat administrator, original message author signature + */ +final case class MessageOriginChat( + `type`: String, + date: Int, + senderChat: Chat, + authorSignature: Option[String] = Option.empty +) extends MessageOrigin diff --git a/telegramium-core/src/main/scala/telegramium/bots/MessageReactionCountUpdated.scala b/telegramium-core/src/main/scala/telegramium/bots/MessageReactionCountUpdated.scala new file mode 100644 index 00000000..1a6886e8 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/MessageReactionCountUpdated.scala @@ -0,0 +1,19 @@ +package telegramium.bots + +/** This object represents reaction changes on a message with anonymous reactions. + * + * @param chat + * The chat containing the message + * @param messageId + * Unique message identifier inside the chat + * @param date + * Date of the change in Unix time + * @param reactions + * List of reactions that are present on the message + */ +final case class MessageReactionCountUpdated( + chat: Chat, + messageId: Int, + date: Int, + reactions: List[ReactionCount] = List.empty +) diff --git a/telegramium-core/src/main/scala/telegramium/bots/MessageReactionUpdated.scala b/telegramium-core/src/main/scala/telegramium/bots/MessageReactionUpdated.scala new file mode 100644 index 00000000..d5acc267 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/MessageReactionUpdated.scala @@ -0,0 +1,28 @@ +package telegramium.bots + +/** This object represents a change of a reaction on a message performed by a user. + * + * @param chat + * The chat containing the message the user reacted to + * @param messageId + * Unique identifier of the message inside the chat + * @param date + * Date of the change in Unix time + * @param user + * Optional. The user that changed the reaction, if the user isn't anonymous + * @param actorChat + * Optional. The chat on behalf of which the reaction was changed, if the user is anonymous + * @param oldReaction + * Previous list of reaction types that were set by the user + * @param newReaction + * New list of reaction types that have been set by the user + */ +final case class MessageReactionUpdated( + chat: Chat, + messageId: Int, + date: Int, + user: Option[User] = Option.empty, + actorChat: Option[Chat] = Option.empty, + oldReaction: List[ReactionType] = List.empty, + newReaction: List[ReactionType] = List.empty +) diff --git a/telegramium-core/src/main/scala/telegramium/bots/ReactionCount.scala b/telegramium-core/src/main/scala/telegramium/bots/ReactionCount.scala new file mode 100644 index 00000000..d7e83b29 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/ReactionCount.scala @@ -0,0 +1,10 @@ +package telegramium.bots + +/** Represents a reaction added to a message along with the number of times it was added. + * + * @param type + * Type of the reaction + * @param totalCount + * Number of times the reaction was added + */ +final case class ReactionCount(`type`: ReactionType, totalCount: Int) diff --git a/telegramium-core/src/main/scala/telegramium/bots/ReactionType.scala b/telegramium-core/src/main/scala/telegramium/bots/ReactionType.scala new file mode 100644 index 00000000..5e11d449 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/ReactionType.scala @@ -0,0 +1,25 @@ +package telegramium.bots + +sealed trait ReactionType {} + +/** The reaction is based on an emoji. + * + * @param type + * Type of the reaction, always “emoji” + * @param emoji + * Reaction emoji. Currently, it can be one of "👍", "👎", "❤", "🔥", "🥰", "👏", "😁", "🤔", "🤯", "😱", "🤬", "😢", + * "🎉", "🤩", "🤮", "💩", "🙏", "👌", "🕊", "🤡", "🥱", "🥴", "😍", "🐳", "❤‍🔥", "🌚", "🌭", "💯", "🤣", "⚡", "🍌", + * "🏆", "💔", "🤨", "😐", "🍓", "🍾", "💋", "🖕", "😈", "😴", "😭", "🤓", "👻", "👨‍💻", "👀", "🎃", "🙈", "😇", + * "😨", "🤝", "✍", "🤗", "🫡", "🎅", "🎄", "☃", "💅", "🤪", "🗿", "🆒", "💘", "🙉", "🦄", "😘", "💊", "🙊", "😎", + * "👾", "🤷‍♂", "🤷", "🤷‍♀", "😡" + */ +final case class ReactionTypeEmoji(`type`: String, emoji: String) extends ReactionType + +/** The reaction is based on a custom emoji. + * + * @param type + * Type of the reaction, always “custom_emoji” + * @param customEmojiId + * Custom emoji identifier + */ +final case class ReactionTypeCustomEmoji(`type`: String, customEmojiId: String) extends ReactionType diff --git a/telegramium-core/src/main/scala/telegramium/bots/ReplyParameters.scala b/telegramium-core/src/main/scala/telegramium/bots/ReplyParameters.scala new file mode 100644 index 00000000..70ad8240 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/ReplyParameters.scala @@ -0,0 +1,33 @@ +package telegramium.bots + +/** Describes reply parameters for the message that is being sent. + * + * @param messageId + * Identifier of the message that will be replied to in the current chat, or in the chat chat_id if it is specified + * @param chatId + * Optional. If the message to be replied to is from a different chat, unique identifier for the chat or username of + * the channel (in the format @channelusername) + * @param allowSendingWithoutReply + * Optional. Pass True if the message should be sent even if the specified message to be replied to is not found; can + * be used only for replies in the same chat and forum topic. + * @param quote + * Optional. Quoted part of the message to be replied to; 0-1024 characters after entities parsing. The quote must be + * an exact substring of the message to be replied to, including bold, italic, underline, strikethrough, spoiler, and + * custom_emoji entities. The message will fail to send if the quote isn't found in the original message. + * @param quoteParseMode + * Optional. Mode for parsing entities in the quote. See formatting options for more details. + * @param quoteEntities + * Optional. A JSON-serialized list of special entities that appear in the quote. It can be specified instead of + * quote_parse_mode. + * @param quotePosition + * Optional. Position of the quote in the original message in UTF-16 code units + */ +final case class ReplyParameters( + messageId: Int, + chatId: Option[ChatId] = Option.empty, + allowSendingWithoutReply: Option[Boolean] = Option.empty, + quote: Option[String] = Option.empty, + quoteParseMode: Option[ParseMode] = Option.empty, + quoteEntities: List[MessageEntity] = List.empty, + quotePosition: Option[Int] = Option.empty +) diff --git a/telegramium-core/src/main/scala/telegramium/bots/TextQuote.scala b/telegramium-core/src/main/scala/telegramium/bots/TextQuote.scala new file mode 100644 index 00000000..ad8481b4 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/TextQuote.scala @@ -0,0 +1,21 @@ +package telegramium.bots + +/** This object contains information about the quoted part of a message that is replied to by the given message. + * + * @param text + * Text of the quoted part of a message that is replied to by the given message + * @param position + * Approximate quote position in the original message in UTF-16 code units as specified by the sender + * @param entities + * Optional. Special entities that appear in the quote. Currently, only bold, italic, underline, strikethrough, + * spoiler, and custom_emoji entities are kept in quotes. + * @param isManual + * Optional. True, if the quote was chosen manually by the message sender. Otherwise, the quote was added + * automatically by the server. + */ +final case class TextQuote( + text: String, + position: Int, + entities: List[MessageEntity] = List.empty, + isManual: Option[Boolean] = Option.empty +) diff --git a/telegramium-core/src/main/scala/telegramium/bots/Update.scala b/telegramium-core/src/main/scala/telegramium/bots/Update.scala index f60ea634..f828b4d8 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/Update.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/Update.scala @@ -16,6 +16,13 @@ package telegramium.bots * Optional. New incoming channel post of any kind - text, photo, sticker, etc. * @param editedChannelPost * Optional. New version of a channel post that is known to the bot and was edited + * @param messageReaction + * Optional. A reaction to a message was changed by a user. The bot must be an administrator in the chat and must + * explicitly specify "message_reaction" in the list of allowed_updates to receive these updates. The update isn't + * received for reactions set by bots. + * @param messageReactionCount + * Optional. Reactions to a message with anonymous reactions were changed. The bot must be an administrator in the + * chat and must explicitly specify "message_reaction_count" in the list of allowed_updates to receive these updates. * @param inlineQuery * Optional. New incoming inline query * @param chosenInlineResult @@ -37,10 +44,15 @@ package telegramium.bots * the bot is blocked or unblocked by the user. * @param chatMember * Optional. A chat member's status was updated in a chat. The bot must be an administrator in the chat and must - * explicitly specify “chat_member” in the list of allowed_updates to receive these updates. + * explicitly specify "chat_member" in the list of allowed_updates to receive these updates. * @param chatJoinRequest * Optional. A request to join the chat has been sent. The bot must have the can_invite_users administrator right in * the chat to receive these updates. + * @param chatBoost + * Optional. A chat boost was added or changed. The bot must be an administrator in the chat to receive these + * updates. + * @param removedChatBoost + * Optional. A boost was removed from a chat. The bot must be an administrator in the chat to receive these updates. */ final case class Update( updateId: Int, @@ -48,6 +60,8 @@ final case class Update( editedMessage: Option[Message] = Option.empty, channelPost: Option[Message] = Option.empty, editedChannelPost: Option[Message] = Option.empty, + messageReaction: Option[MessageReactionUpdated] = Option.empty, + messageReactionCount: Option[MessageReactionCountUpdated] = Option.empty, inlineQuery: Option[InlineQuery] = Option.empty, chosenInlineResult: Option[ChosenInlineResult] = Option.empty, callbackQuery: Option[CallbackQuery] = Option.empty, @@ -57,5 +71,7 @@ final case class Update( pollAnswer: Option[PollAnswer] = Option.empty, myChatMember: Option[ChatMemberUpdated] = Option.empty, chatMember: Option[ChatMemberUpdated] = Option.empty, - chatJoinRequest: Option[ChatJoinRequest] = Option.empty + chatJoinRequest: Option[ChatJoinRequest] = Option.empty, + chatBoost: Option[ChatBoostUpdated] = Option.empty, + removedChatBoost: Option[ChatBoostRemoved] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/UserChatBoosts.scala b/telegramium-core/src/main/scala/telegramium/bots/UserChatBoosts.scala new file mode 100644 index 00000000..f69ef16b --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/UserChatBoosts.scala @@ -0,0 +1,8 @@ +package telegramium.bots + +/** This object represents a list of boosts added to a chat by a user. + * + * @param boosts + * The list of boosts added to the chat by the user + */ +final case class UserChatBoosts(boosts: List[ChatBoost] = List.empty) diff --git a/telegramium-core/src/main/scala/telegramium/bots/UserShared.scala b/telegramium-core/src/main/scala/telegramium/bots/UserShared.scala deleted file mode 100644 index 68b4e8d4..00000000 --- a/telegramium-core/src/main/scala/telegramium/bots/UserShared.scala +++ /dev/null @@ -1,14 +0,0 @@ -package telegramium.bots - -/** This object contains information about the user whose identifier was shared with the bot using a - * KeyboardButtonRequestUser button. - * - * @param requestId - * Identifier of the request - * @param userId - * Identifier of the shared user. This number may have more than 32 significant bits and some programming languages - * may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a 64-bit integer - * or double-precision float type are safe for storing this identifier. The bot may not have access to the user and - * could be unable to use this identifier, unless the user is already known to the bot by some other means. - */ -final case class UserShared(requestId: Int, userId: Long) diff --git a/telegramium-core/src/main/scala/telegramium/bots/UsersShared.scala b/telegramium-core/src/main/scala/telegramium/bots/UsersShared.scala new file mode 100644 index 00000000..471e5d3d --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/UsersShared.scala @@ -0,0 +1,15 @@ +package telegramium.bots + +/** This object contains information about the users whose identifiers were shared with the bot using a + * KeyboardButtonRequestUsers button. + * + * @param requestId + * Identifier of the request + * @param userIds + * Identifiers of the shared users. These numbers may have more than 32 significant bits and some programming + * languages may have difficulty/silent defects in interpreting them. But they have at most 52 significant bits, so + * 64-bit integers or double-precision float types are safe for storing these identifiers. The bot may not have + * access to the users and could be unable to use these identifiers, unless the users are already known to the bot by + * some other means. + */ +final case class UsersShared(requestId: Int, userIds: List[Long] = List.empty) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/CopyMessageReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/CopyMessageReq.scala index fdbe2baa..8938c25b 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/CopyMessageReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/CopyMessageReq.scala @@ -3,6 +3,7 @@ package telegramium.bots.client import telegramium.bots.ChatId import telegramium.bots.ParseMode import telegramium.bots.MessageEntity +import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup /** @param chatId @@ -25,10 +26,8 @@ import telegramium.bots.KeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions * to remove reply keyboard or to force a reply from the user. @@ -43,7 +42,6 @@ final case class CopyMessageReq( captionEntities: List[MessageEntity] = List.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/CopyMessagesReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/CopyMessagesReq.scala new file mode 100644 index 00000000..aaf372a5 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/client/CopyMessagesReq.scala @@ -0,0 +1,30 @@ +package telegramium.bots.client + +import telegramium.bots.ChatId + +/** @param chatId + * Unique identifier for the target chat or username of the target channel (in the format @channelusername) + * @param fromChatId + * Unique identifier for the chat where the original messages were sent (or channel username in the format + * @channelusername) + * @param messageThreadId + * Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + * @param messageIds + * Identifiers of 1-100 messages in the chat from_chat_id to copy. The identifiers must be specified in a strictly + * increasing order. + * @param disableNotification + * Sends the messages silently. Users will receive a notification with no sound. + * @param protectContent + * Protects the contents of the sent messages from forwarding and saving + * @param removeCaption + * Pass True to copy the messages without their captions + */ +final case class CopyMessagesReq( + chatId: ChatId, + fromChatId: ChatId, + messageThreadId: Option[Int] = Option.empty, + messageIds: List[Int] = List.empty, + disableNotification: Option[Boolean] = Option.empty, + protectContent: Option[Boolean] = Option.empty, + removeCaption: Option[Boolean] = Option.empty +) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/DeleteMessagesReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/DeleteMessagesReq.scala new file mode 100644 index 00000000..75bfc47a --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/client/DeleteMessagesReq.scala @@ -0,0 +1,10 @@ +package telegramium.bots.client + +import telegramium.bots.ChatId + +/** @param chatId + * Unique identifier for the target chat or username of the target channel (in the format @channelusername) + * @param messageIds + * Identifiers of 1-100 messages to delete. See deleteMessage for limitations on which messages can be deleted + */ +final case class DeleteMessagesReq(chatId: ChatId, messageIds: List[Int] = List.empty) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/EditMessageTextReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/EditMessageTextReq.scala index 6b78b596..b554bc0a 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/EditMessageTextReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/EditMessageTextReq.scala @@ -3,6 +3,7 @@ package telegramium.bots.client import telegramium.bots.ChatId import telegramium.bots.ParseMode import telegramium.bots.MessageEntity +import telegramium.bots.LinkPreviewOptions import telegramium.bots.InlineKeyboardMarkup /** @param text @@ -19,8 +20,8 @@ import telegramium.bots.InlineKeyboardMarkup * @param entities * A JSON-serialized list of special entities that appear in message text, which can be specified instead of * parse_mode - * @param disableWebPagePreview - * Disables link previews for links in this message + * @param linkPreviewOptions + * Link preview generation options for the message * @param replyMarkup * A JSON-serialized object for an inline keyboard. */ @@ -31,6 +32,6 @@ final case class EditMessageTextReq( inlineMessageId: Option[String] = Option.empty, parseMode: Option[ParseMode] = Option.empty, entities: List[MessageEntity] = List.empty, - disableWebPagePreview: Option[Boolean] = Option.empty, + linkPreviewOptions: Option[LinkPreviewOptions] = Option.empty, replyMarkup: Option[InlineKeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/ForwardMessagesReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/ForwardMessagesReq.scala new file mode 100644 index 00000000..9dc06d27 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/client/ForwardMessagesReq.scala @@ -0,0 +1,27 @@ +package telegramium.bots.client + +import telegramium.bots.ChatId + +/** @param chatId + * Unique identifier for the target chat or username of the target channel (in the format @channelusername) + * @param fromChatId + * Unique identifier for the chat where the original messages were sent (or channel username in the format + * @channelusername) + * @param messageThreadId + * Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + * @param messageIds + * Identifiers of 1-100 messages in the chat from_chat_id to forward. The identifiers must be specified in a strictly + * increasing order. + * @param disableNotification + * Sends the messages silently. Users will receive a notification with no sound. + * @param protectContent + * Protects the contents of the forwarded messages from forwarding and saving + */ +final case class ForwardMessagesReq( + chatId: ChatId, + fromChatId: ChatId, + messageThreadId: Option[Int] = Option.empty, + messageIds: List[Int] = List.empty, + disableNotification: Option[Boolean] = Option.empty, + protectContent: Option[Boolean] = Option.empty +) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/GetUpdatesReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/GetUpdatesReq.scala index 7c543dc4..e85244d3 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/GetUpdatesReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/GetUpdatesReq.scala @@ -12,11 +12,12 @@ package telegramium.bots.client * Timeout in seconds for long polling. Defaults to 0, i.e. usual short polling. Should be positive, short polling * should be used for testing purposes only. * @param allowedUpdates - * A JSON-serialized list of the update types you want your bot to receive. For example, specify [“message”, - * “edited_channel_post”, “callback_query”] to only receive updates of these types. See Update for a complete list of - * available update types. Specify an empty list to receive all update types except chat_member (default). If not - * specified, the previous setting will be used. Please note that this parameter doesn't affect updates created - * before the call to the getUpdates, so unwanted updates may be received for a short period of time. + * A JSON-serialized list of the update types you want your bot to receive. For example, specify ["message", + * "edited_channel_post", "callback_query"] to only receive updates of these types. See Update for a complete list of + * available update types. Specify an empty list to receive all update types except chat_member, message_reaction, + * and message_reaction_count (default). If not specified, the previous setting will be used. Please note that this + * parameter doesn't affect updates created before the call to the getUpdates, so unwanted updates may be received + * for a short period of time. */ final case class GetUpdatesReq( offset: Option[Int] = Option.empty, diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/GetUserChatBoostsReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/GetUserChatBoostsReq.scala new file mode 100644 index 00000000..e83bebdb --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/client/GetUserChatBoostsReq.scala @@ -0,0 +1,10 @@ +package telegramium.bots.client + +import telegramium.bots.ChatId + +/** @param chatId + * Unique identifier for the chat or username of the channel (in the format @channelusername) + * @param userId + * Unique identifier of the target user + */ +final case class GetUserChatBoostsReq(chatId: ChatId, userId: Long) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/Methods.scala b/telegramium-core/src/main/scala/telegramium/bots/client/Methods.scala index a1f74854..3c26e870 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/Methods.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/Methods.scala @@ -5,6 +5,7 @@ import CirceImplicits._ import telegramium.bots.WebhookInfo import telegramium.bots._ import telegramium.bots.CirceImplicits._ +import telegramium.bots.UserChatBoosts import telegramium.bots.GameHighScore import telegramium.bots.Sticker import telegramium.bots.BotName @@ -13,11 +14,11 @@ import telegramium.bots.Message import telegramium.bots.UserProfilePhotos import telegramium.bots.SentWebAppMessage import telegramium.bots.File +import telegramium.bots.MessageId import telegramium.bots.BotShortDescription import telegramium.bots.Poll import telegramium.bots.ForumTopic import telegramium.bots.BotDescription -import telegramium.bots.MessageId import telegramium.bots.ChatInviteLink import telegramium.bots.User import telegramium.bots.ChatMember @@ -91,6 +92,19 @@ trait Methods { MethodReq[Boolean]("setMyCommands", req.asJson) } + /** Use this method to get the list of boosts added to a chat by a user. Requires administrator rights in the chat. + * Returns a UserChatBoosts object. + * + * @param chatId + * Unique identifier for the chat or username of the channel (in the format @channelusername) + * @param userId + * Unique identifier of the target user + */ + def getUserChatBoosts(chatId: ChatId, userId: Long): Method[UserChatBoosts] = { + val req = GetUserChatBoostsReq(chatId, userId) + MethodReq[UserChatBoosts]("getUserChatBoosts", req.asJson) + } + /** Use this method to set a new profile photo for the chat. Photos can't be changed for private chats. The bot must * be an administrator in the chat for this to work and must have the appropriate administrator rights. Returns True * on success. @@ -231,16 +245,14 @@ trait Methods { * @param entities * A JSON-serialized list of special entities that appear in message text, which can be specified instead of * parse_mode - * @param disableWebPagePreview - * Disables link previews for links in this message + * @param linkPreviewOptions + * Link preview generation options for the message * @param disableNotification * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, * instructions to remove reply keyboard or to force a reply from the user. @@ -251,11 +263,10 @@ trait Methods { messageThreadId: Option[Int] = Option.empty, parseMode: Option[ParseMode] = Option.empty, entities: List[MessageEntity] = List.empty, - disableWebPagePreview: Option[Boolean] = Option.empty, + linkPreviewOptions: Option[LinkPreviewOptions] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ): Method[Message] = { val req = SendMessageReq( @@ -264,11 +275,10 @@ trait Methods { messageThreadId, parseMode, entities, - disableWebPagePreview, + linkPreviewOptions, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[Message]("sendMessage", req.asJson) @@ -329,10 +339,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, * instructions to remove reply keyboard or to force a reply from the user. @@ -347,15 +355,14 @@ trait Methods { allowsMultipleAnswers: Option[Boolean] = Option.empty, correctOptionId: Option[Int] = Option.empty, explanation: Option[String] = Option.empty, - explanationParseMode: Option[String] = Option.empty, + explanationParseMode: Option[ParseMode] = Option.empty, explanationEntities: List[MessageEntity] = List.empty, openPeriod: Option[Int] = Option.empty, closeDate: Option[Int] = Option.empty, isClosed: Option[Boolean] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ): Method[Message] = { val req = SendPollReq( @@ -375,8 +382,7 @@ trait Methods { isClosed, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[Message]("sendPoll", req.asJson) @@ -413,10 +419,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, * instructions to remove reply keyboard or to force a reply from the user. @@ -430,8 +434,7 @@ trait Methods { vcard: Option[String] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ): Method[Message] = { val req = SendContactReq( @@ -443,8 +446,7 @@ trait Methods { vcard, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[Message]("sendContact", req.asJson) @@ -519,6 +521,19 @@ trait Methods { ) } + /** Use this method to delete multiple messages simultaneously. If some of the specified messages can't be found, they + * are skipped. Returns True on success. + * + * @param chatId + * Unique identifier for the target chat or username of the target channel (in the format @channelusername) + * @param messageIds + * Identifiers of 1-100 messages to delete. See deleteMessage for limitations on which messages can be deleted + */ + def deleteMessages(chatId: ChatId, messageIds: List[Int] = List.empty): Method[Boolean] = { + val req = DeleteMessagesReq(chatId, messageIds) + MethodReq[Boolean]("deleteMessages", req.asJson) + } + /** Use this method to set default chat permissions for all members. The bot must be an administrator in the group or * a supergroup for this to work and must have the can_restrict_members administrator rights. Returns True on * success. @@ -595,10 +610,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, * instructions to remove reply keyboard or to force a reply from the user. @@ -614,8 +627,7 @@ trait Methods { proximityAlertRadius: Option[Int] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ): Method[Message] = { val req = SendLocationReq( @@ -629,8 +641,7 @@ trait Methods { proximityAlertRadius, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[Message]("sendLocation", req.asJson) @@ -649,6 +660,50 @@ trait Methods { MethodReq[Boolean]("deleteChatStickerSet", req.asJson) } + /** Use this method to copy messages of any kind. If some of the specified messages can't be found or copied, they are + * skipped. Service messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. A + * quiz poll can be copied only if the value of the field correct_option_id is known to the bot. The method is + * analogous to the method forwardMessages, but the copied messages don't have a link to the original message. Album + * grouping is kept for copied messages. On success, an array of MessageId of the sent messages is returned. + * + * @param chatId + * Unique identifier for the target chat or username of the target channel (in the format @channelusername) + * @param fromChatId + * Unique identifier for the chat where the original messages were sent (or channel username in the format + * @channelusername) + * @param messageThreadId + * Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + * @param messageIds + * Identifiers of 1-100 messages in the chat from_chat_id to copy. The identifiers must be specified in a strictly + * increasing order. + * @param disableNotification + * Sends the messages silently. Users will receive a notification with no sound. + * @param protectContent + * Protects the contents of the sent messages from forwarding and saving + * @param removeCaption + * Pass True to copy the messages without their captions + */ + def copyMessages( + chatId: ChatId, + fromChatId: ChatId, + messageThreadId: Option[Int] = Option.empty, + messageIds: List[Int] = List.empty, + disableNotification: Option[Boolean] = Option.empty, + protectContent: Option[Boolean] = Option.empty, + removeCaption: Option[Boolean] = Option.empty + ): Method[List[MessageId]] = { + val req = CopyMessagesReq( + chatId, + fromChatId, + messageThreadId, + messageIds, + disableNotification, + protectContent, + removeCaption + ) + MethodReq[List[MessageId]]("copyMessages", req.asJson) + } + /** Use this method to get the current bot short description for the given user language. Returns BotShortDescription * on success. * @@ -723,10 +778,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, * instructions to remove reply keyboard or to force a reply from the user. @@ -737,20 +790,11 @@ trait Methods { emoji: Option[String] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ): Method[Message] = { - val req = SendDiceReq( - chatId, - messageThreadId, - emoji, - disableNotification, - protectContent, - replyToMessageId, - allowSendingWithoutReply, - replyMarkup - ) + val req = + SendDiceReq(chatId, messageThreadId, emoji, disableNotification, protectContent, replyParameters, replyMarkup) MethodReq[Message]("sendDice", req.asJson) } @@ -957,10 +1001,8 @@ trait Methods { * Sends messages silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent messages from forwarding and saving - * @param replyToMessageId - * If the messages are a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to */ def sendMediaGroup( chatId: ChatId, @@ -968,18 +1010,9 @@ trait Methods { media: List[InputMedia] = List.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty + replyParameters: Option[ReplyParameters] = Option.empty ): Method[List[Message]] = { - val req = SendMediaGroupReq( - chatId, - messageThreadId, - media, - disableNotification, - protectContent, - replyToMessageId, - allowSendingWithoutReply - ) + val req = SendMediaGroupReq(chatId, messageThreadId, media, disableNotification, protectContent, replyParameters) MethodReq[List[Message]]("sendMediaGroup", req.asJson) } @@ -995,10 +1028,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * A JSON-serialized object for an inline keyboard. If empty, one 'Play game_title' button will be shown. If not * empty, the first button must launch the game. @@ -1009,8 +1040,7 @@ trait Methods { messageThreadId: Option[Int] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[InlineKeyboardMarkup] = Option.empty ): Method[Message] = { val req = SendGameReq( @@ -1019,8 +1049,7 @@ trait Methods { messageThreadId, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[Message]("sendGame", req.asJson) @@ -1053,10 +1082,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, * instructions to remove reply keyboard or to force a reply from the user. @@ -1074,8 +1101,7 @@ trait Methods { googlePlaceType: Option[String] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ): Method[Message] = { val req = SendVenueReq( @@ -1091,8 +1117,7 @@ trait Methods { googlePlaceType, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[Message]("sendVenue", req.asJson) @@ -1214,8 +1239,8 @@ trait Methods { * @param entities * A JSON-serialized list of special entities that appear in message text, which can be specified instead of * parse_mode - * @param disableWebPagePreview - * Disables link previews for links in this message + * @param linkPreviewOptions + * Link preview generation options for the message * @param replyMarkup * A JSON-serialized object for an inline keyboard. */ @@ -1226,19 +1251,11 @@ trait Methods { inlineMessageId: Option[String] = Option.empty, parseMode: Option[ParseMode] = Option.empty, entities: List[MessageEntity] = List.empty, - disableWebPagePreview: Option[Boolean] = Option.empty, + linkPreviewOptions: Option[LinkPreviewOptions] = Option.empty, replyMarkup: Option[InlineKeyboardMarkup] = Option.empty ): Method[Either[Boolean, Message]] = { - val req = EditMessageTextReq( - text, - chatId, - messageId, - inlineMessageId, - parseMode, - entities, - disableWebPagePreview, - replyMarkup - ) + val req = + EditMessageTextReq(text, chatId, messageId, inlineMessageId, parseMode, entities, linkPreviewOptions, replyMarkup) MethodReq[Either[Boolean, Message]]("editMessageText", req.asJson) } @@ -1388,10 +1405,10 @@ trait Methods { MethodReq[Boolean]("setChatTitle", req.asJson) } - /** Use this method to copy messages of any kind. Service messages and invoice messages can't be copied. A quiz poll - * can be copied only if the value of the field correct_option_id is known to the bot. The method is analogous to the - * method forwardMessage, but the copied message doesn't have a link to the original message. Returns the MessageId - * of the sent message on success. + /** Use this method to copy messages of any kind. Service messages, giveaway messages, giveaway winners messages, and + * invoice messages can't be copied. A quiz poll can be copied only if the value of the field correct_option_id is + * known to the bot. The method is analogous to the method forwardMessage, but the copied message doesn't have a link + * to the original message. Returns the MessageId of the sent message on success. * * @param chatId * Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -1413,10 +1430,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, * instructions to remove reply keyboard or to force a reply from the user. @@ -1431,8 +1446,7 @@ trait Methods { captionEntities: List[MessageEntity] = List.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ): Method[MessageId] = { val req = CopyMessageReq( @@ -1445,8 +1459,7 @@ trait Methods { captionEntities, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[MessageId]("copyMessage", req.asJson) @@ -1477,10 +1490,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, * instructions to remove reply keyboard or to force a reply from the user. @@ -1494,8 +1505,7 @@ trait Methods { thumbnail: Option[IFile] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ): Method[Message] = { val req = SendVideoNoteReq( @@ -1507,8 +1517,7 @@ trait Methods { thumbnail, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[Message]( @@ -1658,10 +1667,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * A JSON-serialized object for an inline keyboard. If empty, one 'Pay total price' button will be shown. If not * empty, the first button must be a Pay button. @@ -1692,8 +1699,7 @@ trait Methods { isFlexible: Option[Boolean] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[InlineKeyboardMarkup] = Option.empty ): Method[Message] = { val req = SendInvoiceReq( @@ -1722,8 +1728,7 @@ trait Methods { isFlexible, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[Message]("sendInvoice", req.asJson) @@ -1772,10 +1777,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, * instructions to remove reply keyboard or to force a reply from the user. @@ -1791,8 +1794,7 @@ trait Methods { disableContentTypeDetection: Option[Boolean] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ): Method[Message] = { val req = SendDocumentReq( @@ -1806,8 +1808,7 @@ trait Methods { disableContentTypeDetection, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[Message]( @@ -1929,10 +1930,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, * instructions to remove reply keyboard or to force a reply from the user. @@ -1950,8 +1949,7 @@ trait Methods { thumbnail: Option[IFile] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ): Method[Message] = { val req = SendAudioReq( @@ -1967,8 +1965,7 @@ trait Methods { thumbnail, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[Message]( @@ -2035,8 +2032,8 @@ trait Methods { MethodReq[User]("getMe", req.asJson) } - /** Use this method to forward messages of any kind. Service messages can't be forwarded. On success, the sent Message - * is returned. + /** Use this method to forward messages of any kind. Service messages and messages with protected content can't be + * forwarded. On success, the sent Message is returned. * * @param chatId * Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -2160,10 +2157,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, * instructions to remove reply keyboard or to force a reply from the user. @@ -2178,8 +2173,7 @@ trait Methods { duration: Option[Int] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ): Method[Message] = { val req = SendVoiceReq( @@ -2192,8 +2186,7 @@ trait Methods { duration, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[Message]("sendVoice", req.asJson, Map("voice" -> Option(voice)).collect { case (k, Some(v)) => k -> v }) @@ -2220,25 +2213,15 @@ trait Methods { * @param isAnonymous * Pass True if the administrator's presence in the chat is hidden * @param canManageChat - * Pass True if the administrator can access the chat event log, chat statistics, boost list in channels, message - * statistics in channels, see channel members, see anonymous administrators in supergroups and ignore slow mode. - * Implied by any other administrator privilege - * @param canPostMessages - * Pass True if the administrator can post messages in the channel; channels only - * @param canEditMessages - * Pass True if the administrator can edit messages of other users and can pin messages; channels only + * Pass True if the administrator can access the chat event log, boost list in channels, see channel members, + * report spam messages, see anonymous administrators in supergroups and ignore slow mode. Implied by any other + * administrator privilege * @param canDeleteMessages * Pass True if the administrator can delete messages of other users - * @param canPostStories - * Pass True if the administrator can post stories in the channel; channels only - * @param canEditStories - * Pass True if the administrator can edit stories posted by other users; channels only - * @param canDeleteStories - * Pass True if the administrator can delete stories posted by other users; channels only * @param canManageVideoChats * Pass True if the administrator can manage video chats * @param canRestrictMembers - * Pass True if the administrator can restrict, ban or unban chat members + * Pass True if the administrator can restrict, ban or unban chat members, or access supergroup statistics * @param canPromoteMembers * Pass True if the administrator can add new administrators with a subset of their own privileges or demote * administrators that they have promoted, directly or indirectly (promoted by administrators that were appointed @@ -2247,8 +2230,18 @@ trait Methods { * Pass True if the administrator can change chat title, photo and other settings * @param canInviteUsers * Pass True if the administrator can invite new users to the chat + * @param canPostMessages + * Pass True if the administrator can post messages in the channel, or access channel statistics; channels only + * @param canEditMessages + * Pass True if the administrator can edit messages of other users and can pin messages; channels only * @param canPinMessages * Pass True if the administrator can pin messages, supergroups only + * @param canPostStories + * Pass True if the administrator can post stories in the channel; channels only + * @param canEditStories + * Pass True if the administrator can edit stories posted by other users; channels only + * @param canDeleteStories + * Pass True if the administrator can delete stories posted by other users; channels only * @param canManageTopics * Pass True if the user is allowed to create, rename, close, and reopen forum topics, supergroups only */ @@ -2257,18 +2250,18 @@ trait Methods { userId: Long, isAnonymous: Option[Boolean] = Option.empty, canManageChat: Option[Boolean] = Option.empty, - canPostMessages: Option[Boolean] = Option.empty, - canEditMessages: Option[Boolean] = Option.empty, canDeleteMessages: Option[Boolean] = Option.empty, - canPostStories: Option[Boolean] = Option.empty, - canEditStories: Option[Boolean] = Option.empty, - canDeleteStories: Option[Boolean] = Option.empty, canManageVideoChats: Option[Boolean] = Option.empty, canRestrictMembers: Option[Boolean] = Option.empty, canPromoteMembers: Option[Boolean] = Option.empty, canChangeInfo: Option[Boolean] = Option.empty, canInviteUsers: Option[Boolean] = Option.empty, + canPostMessages: Option[Boolean] = Option.empty, + canEditMessages: Option[Boolean] = Option.empty, canPinMessages: Option[Boolean] = Option.empty, + canPostStories: Option[Boolean] = Option.empty, + canEditStories: Option[Boolean] = Option.empty, + canDeleteStories: Option[Boolean] = Option.empty, canManageTopics: Option[Boolean] = Option.empty ): Method[Boolean] = { val req = PromoteChatMemberReq( @@ -2276,18 +2269,18 @@ trait Methods { userId, isAnonymous, canManageChat, - canPostMessages, - canEditMessages, canDeleteMessages, - canPostStories, - canEditStories, - canDeleteStories, canManageVideoChats, canRestrictMembers, canPromoteMembers, canChangeInfo, canInviteUsers, + canPostMessages, + canEditMessages, canPinMessages, + canPostStories, + canEditStories, + canDeleteStories, canManageTopics ) MethodReq[Boolean]("promoteChatMember", req.asJson) @@ -2527,10 +2520,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, * instructions to remove reply keyboard or to force a reply from the user. @@ -2550,8 +2541,7 @@ trait Methods { supportsStreaming: Option[Boolean] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ): Method[Message] = { val req = SendVideoReq( @@ -2569,8 +2559,7 @@ trait Methods { supportsStreaming, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[Message]( @@ -2595,8 +2584,7 @@ trait Methods { MethodReq[Boolean]("setChatStickerSet", req.asJson) } - /** Use this method to get up to date information about the chat (current name of the user for one-on-one - * conversations, current username of a user, group or channel, etc.). Returns a Chat object on success. + /** Use this method to get up to date information about the chat. Returns a Chat object on success. * * @param chatId * Unique identifier for the target chat or username of the target supergroup or channel (in the format @@ -2746,10 +2734,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, * instructions to remove reply keyboard or to force a reply from the user. @@ -2768,8 +2754,7 @@ trait Methods { hasSpoiler: Option[Boolean] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ): Method[Message] = { val req = SendAnimationReq( @@ -2786,8 +2771,7 @@ trait Methods { hasSpoiler, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[Message]( @@ -2924,10 +2908,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, * instructions to remove reply keyboard or to force a reply from the user. @@ -2939,8 +2921,7 @@ trait Methods { emoji: Option[String] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ): Method[Message] = { val req = SendStickerReq( @@ -2950,8 +2931,7 @@ trait Methods { emoji, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[Message]( @@ -3013,6 +2993,37 @@ trait Methods { MethodReq[Boolean]("setMyName", req.asJson) } + /** Use this method to forward multiple messages of any kind. If some of the specified messages can't be found or + * forwarded, they are skipped. Service messages and messages with protected content can't be forwarded. Album + * grouping is kept for forwarded messages. On success, an array of MessageId of the sent messages is returned. + * + * @param chatId + * Unique identifier for the target chat or username of the target channel (in the format @channelusername) + * @param fromChatId + * Unique identifier for the chat where the original messages were sent (or channel username in the format + * @channelusername) + * @param messageThreadId + * Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + * @param messageIds + * Identifiers of 1-100 messages in the chat from_chat_id to forward. The identifiers must be specified in a + * strictly increasing order. + * @param disableNotification + * Sends the messages silently. Users will receive a notification with no sound. + * @param protectContent + * Protects the contents of the forwarded messages from forwarding and saving + */ + def forwardMessages( + chatId: ChatId, + fromChatId: ChatId, + messageThreadId: Option[Int] = Option.empty, + messageIds: List[Int] = List.empty, + disableNotification: Option[Boolean] = Option.empty, + protectContent: Option[Boolean] = Option.empty + ): Method[List[MessageId]] = { + val req = ForwardMessagesReq(chatId, fromChatId, messageThreadId, messageIds, disableNotification, protectContent) + MethodReq[List[MessageId]]("forwardMessages", req.asJson) + } + /** Use this method to send photos. On success, the sent Message is returned. * * @param chatId @@ -3037,10 +3048,8 @@ trait Methods { * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, * instructions to remove reply keyboard or to force a reply from the user. @@ -3055,8 +3064,7 @@ trait Methods { hasSpoiler: Option[Boolean] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ): Method[Message] = { val req = SendPhotoReq( @@ -3069,8 +3077,7 @@ trait Methods { hasSpoiler, disableNotification, protectContent, - replyToMessageId, - allowSendingWithoutReply, + replyParameters, replyMarkup ) MethodReq[Message]("sendPhoto", req.asJson, Map("photo" -> Option(photo)).collect { case (k, Some(v)) => k -> v }) @@ -3090,11 +3097,12 @@ trait Methods { * Timeout in seconds for long polling. Defaults to 0, i.e. usual short polling. Should be positive, short polling * should be used for testing purposes only. * @param allowedUpdates - * A JSON-serialized list of the update types you want your bot to receive. For example, specify [“message”, - * “edited_channel_post”, “callback_query”] to only receive updates of these types. See Update for a complete list - * of available update types. Specify an empty list to receive all update types except chat_member (default). If - * not specified, the previous setting will be used. Please note that this parameter doesn't affect updates created - * before the call to the getUpdates, so unwanted updates may be received for a short period of time. + * A JSON-serialized list of the update types you want your bot to receive. For example, specify ["message", + * "edited_channel_post", "callback_query"] to only receive updates of these types. See Update for a complete list + * of available update types. Specify an empty list to receive all update types except chat_member, + * message_reaction, and message_reaction_count (default). If not specified, the previous setting will be used. + * Please note that this parameter doesn't affect updates created before the call to the getUpdates, so unwanted + * updates may be received for a short period of time. */ def getUpdates( offset: Option[Int] = Option.empty, @@ -3135,11 +3143,12 @@ trait Methods { * to 40. Use lower values to limit the load on your bot's server, and higher values to increase your bot's * throughput. * @param allowedUpdates - * A JSON-serialized list of the update types you want your bot to receive. For example, specify [“message”, - * “edited_channel_post”, “callback_query”] to only receive updates of these types. See Update for a complete list - * of available update types. Specify an empty list to receive all update types except chat_member (default). If - * not specified, the previous setting will be used. Please note that this parameter doesn't affect updates created - * before the call to the setWebhook, so unwanted updates may be received for a short period of time. + * A JSON-serialized list of the update types you want your bot to receive. For example, specify ["message", + * "edited_channel_post", "callback_query"] to only receive updates of these types. See Update for a complete list + * of available update types. Specify an empty list to receive all update types except chat_member, + * message_reaction, and message_reaction_count (default). If not specified, the previous setting will be used. + * Please note that this parameter doesn't affect updates created before the call to the setWebhook, so unwanted + * updates may be received for a short period of time. * @param dropPendingUpdates * Pass True to drop all pending updates * @param secretToken @@ -3178,4 +3187,29 @@ trait Methods { MethodReq[Boolean]("setStickerKeywords", req.asJson) } + /** Use this method to change the chosen reactions on a message. Service messages can't be reacted to. Automatically + * forwarded messages from a channel to its discussion group have the same available reactions as messages in the + * channel. In albums, bots must react to the first message. Returns True on success. + * + * @param chatId + * Unique identifier for the target chat or username of the target channel (in the format @channelusername) + * @param messageId + * Identifier of the target message + * @param reaction + * New list of reaction types to set on the message. Currently, as non-premium users, bots can set up to one + * reaction per message. A custom emoji reaction can be used if it is either already present on the message or + * explicitly allowed by chat administrators. + * @param isBig + * Pass True to set the reaction with a big animation + */ + def setMessageReaction( + chatId: ChatId, + messageId: Int, + reaction: List[ReactionType] = List.empty, + isBig: Option[Boolean] = Option.empty + ): Method[Boolean] = { + val req = SetMessageReactionReq(chatId, messageId, reaction, isBig) + MethodReq[Boolean]("setMessageReaction", req.asJson) + } + } diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/PromoteChatMemberReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/PromoteChatMemberReq.scala index 9f488004..0b0fb96b 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/PromoteChatMemberReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/PromoteChatMemberReq.scala @@ -9,25 +9,15 @@ import telegramium.bots.ChatId * @param isAnonymous * Pass True if the administrator's presence in the chat is hidden * @param canManageChat - * Pass True if the administrator can access the chat event log, chat statistics, boost list in channels, message - * statistics in channels, see channel members, see anonymous administrators in supergroups and ignore slow mode. - * Implied by any other administrator privilege - * @param canPostMessages - * Pass True if the administrator can post messages in the channel; channels only - * @param canEditMessages - * Pass True if the administrator can edit messages of other users and can pin messages; channels only + * Pass True if the administrator can access the chat event log, boost list in channels, see channel members, report + * spam messages, see anonymous administrators in supergroups and ignore slow mode. Implied by any other + * administrator privilege * @param canDeleteMessages * Pass True if the administrator can delete messages of other users - * @param canPostStories - * Pass True if the administrator can post stories in the channel; channels only - * @param canEditStories - * Pass True if the administrator can edit stories posted by other users; channels only - * @param canDeleteStories - * Pass True if the administrator can delete stories posted by other users; channels only * @param canManageVideoChats * Pass True if the administrator can manage video chats * @param canRestrictMembers - * Pass True if the administrator can restrict, ban or unban chat members + * Pass True if the administrator can restrict, ban or unban chat members, or access supergroup statistics * @param canPromoteMembers * Pass True if the administrator can add new administrators with a subset of their own privileges or demote * administrators that they have promoted, directly or indirectly (promoted by administrators that were appointed by @@ -36,8 +26,18 @@ import telegramium.bots.ChatId * Pass True if the administrator can change chat title, photo and other settings * @param canInviteUsers * Pass True if the administrator can invite new users to the chat + * @param canPostMessages + * Pass True if the administrator can post messages in the channel, or access channel statistics; channels only + * @param canEditMessages + * Pass True if the administrator can edit messages of other users and can pin messages; channels only * @param canPinMessages * Pass True if the administrator can pin messages, supergroups only + * @param canPostStories + * Pass True if the administrator can post stories in the channel; channels only + * @param canEditStories + * Pass True if the administrator can edit stories posted by other users; channels only + * @param canDeleteStories + * Pass True if the administrator can delete stories posted by other users; channels only * @param canManageTopics * Pass True if the user is allowed to create, rename, close, and reopen forum topics, supergroups only */ @@ -46,17 +46,17 @@ final case class PromoteChatMemberReq( userId: Long, isAnonymous: Option[Boolean] = Option.empty, canManageChat: Option[Boolean] = Option.empty, - canPostMessages: Option[Boolean] = Option.empty, - canEditMessages: Option[Boolean] = Option.empty, canDeleteMessages: Option[Boolean] = Option.empty, - canPostStories: Option[Boolean] = Option.empty, - canEditStories: Option[Boolean] = Option.empty, - canDeleteStories: Option[Boolean] = Option.empty, canManageVideoChats: Option[Boolean] = Option.empty, canRestrictMembers: Option[Boolean] = Option.empty, canPromoteMembers: Option[Boolean] = Option.empty, canChangeInfo: Option[Boolean] = Option.empty, canInviteUsers: Option[Boolean] = Option.empty, + canPostMessages: Option[Boolean] = Option.empty, + canEditMessages: Option[Boolean] = Option.empty, canPinMessages: Option[Boolean] = Option.empty, + canPostStories: Option[Boolean] = Option.empty, + canEditStories: Option[Boolean] = Option.empty, + canDeleteStories: Option[Boolean] = Option.empty, canManageTopics: Option[Boolean] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendAnimationReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendAnimationReq.scala index e5c269eb..649e735f 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendAnimationReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendAnimationReq.scala @@ -4,6 +4,7 @@ import telegramium.bots.ChatId import telegramium.bots.IFile import telegramium.bots.ParseMode import telegramium.bots.MessageEntity +import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup /** @param chatId @@ -39,10 +40,8 @@ import telegramium.bots.KeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions * to remove reply keyboard or to force a reply from the user. @@ -61,7 +60,6 @@ final case class SendAnimationReq( hasSpoiler: Option[Boolean] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendAudioReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendAudioReq.scala index b85b4803..c33e3e84 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendAudioReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendAudioReq.scala @@ -4,6 +4,7 @@ import telegramium.bots.ChatId import telegramium.bots.IFile import telegramium.bots.ParseMode import telegramium.bots.MessageEntity +import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup /** @param chatId @@ -37,10 +38,8 @@ import telegramium.bots.KeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions * to remove reply keyboard or to force a reply from the user. @@ -58,7 +57,6 @@ final case class SendAudioReq( thumbnail: Option[IFile] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendContactReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendContactReq.scala index 8fc3b186..65497c6b 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendContactReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendContactReq.scala @@ -1,6 +1,7 @@ package telegramium.bots.client import telegramium.bots.ChatId +import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup /** @param chatId @@ -19,10 +20,8 @@ import telegramium.bots.KeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions * to remove reply keyboard or to force a reply from the user. @@ -36,7 +35,6 @@ final case class SendContactReq( vcard: Option[String] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendDiceReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendDiceReq.scala index ff5271c4..107a1f62 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendDiceReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendDiceReq.scala @@ -1,6 +1,7 @@ package telegramium.bots.client import telegramium.bots.ChatId +import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup /** @param chatId @@ -15,10 +16,8 @@ import telegramium.bots.KeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions * to remove reply keyboard or to force a reply from the user. @@ -29,7 +28,6 @@ final case class SendDiceReq( emoji: Option[String] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendDocumentReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendDocumentReq.scala index fdd0cf4e..e387ef0c 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendDocumentReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendDocumentReq.scala @@ -4,6 +4,7 @@ import telegramium.bots.ChatId import telegramium.bots.IFile import telegramium.bots.ParseMode import telegramium.bots.MessageEntity +import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup /** @param chatId @@ -32,10 +33,8 @@ import telegramium.bots.KeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions * to remove reply keyboard or to force a reply from the user. @@ -51,7 +50,6 @@ final case class SendDocumentReq( disableContentTypeDetection: Option[Boolean] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendGameReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendGameReq.scala index 5db6918e..51a123c5 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendGameReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendGameReq.scala @@ -1,5 +1,6 @@ package telegramium.bots.client +import telegramium.bots.ReplyParameters import telegramium.bots.InlineKeyboardMarkup /** @param chatId @@ -12,10 +13,8 @@ import telegramium.bots.InlineKeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * A JSON-serialized object for an inline keyboard. If empty, one 'Play game_title' button will be shown. If not * empty, the first button must launch the game. @@ -26,7 +25,6 @@ final case class SendGameReq( messageThreadId: Option[Int] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[InlineKeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendInvoiceReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendInvoiceReq.scala index f7d393ce..b416fff1 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendInvoiceReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendInvoiceReq.scala @@ -2,6 +2,7 @@ package telegramium.bots.client import telegramium.bots.ChatId import telegramium.bots.LabeledPrice +import telegramium.bots.ReplyParameters import telegramium.bots.InlineKeyboardMarkup /** @param chatId @@ -65,10 +66,8 @@ import telegramium.bots.InlineKeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * A JSON-serialized object for an inline keyboard. If empty, one 'Pay total price' button will be shown. If not * empty, the first button must be a Pay button. @@ -99,7 +98,6 @@ final case class SendInvoiceReq( isFlexible: Option[Boolean] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[InlineKeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendLocationReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendLocationReq.scala index c0545aff..296c4771 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendLocationReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendLocationReq.scala @@ -1,6 +1,7 @@ package telegramium.bots.client import telegramium.bots.ChatId +import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup /** @param chatId @@ -24,10 +25,8 @@ import telegramium.bots.KeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions * to remove reply keyboard or to force a reply from the user. @@ -43,7 +42,6 @@ final case class SendLocationReq( proximityAlertRadius: Option[Int] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendMediaGroupReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendMediaGroupReq.scala index 53cf77bc..f3fb226c 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendMediaGroupReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendMediaGroupReq.scala @@ -2,6 +2,7 @@ package telegramium.bots.client import telegramium.bots.ChatId import telegramium.bots.InputMedia +import telegramium.bots.ReplyParameters /** @param chatId * Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -13,10 +14,8 @@ import telegramium.bots.InputMedia * Sends messages silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent messages from forwarding and saving - * @param replyToMessageId - * If the messages are a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to */ final case class SendMediaGroupReq( chatId: ChatId, @@ -24,6 +23,5 @@ final case class SendMediaGroupReq( media: List[InputMedia] = List.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty + replyParameters: Option[ReplyParameters] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendMessageReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendMessageReq.scala index 7e2579db..c893cbce 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendMessageReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendMessageReq.scala @@ -3,6 +3,8 @@ package telegramium.bots.client import telegramium.bots.ChatId import telegramium.bots.ParseMode import telegramium.bots.MessageEntity +import telegramium.bots.LinkPreviewOptions +import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup /** @param chatId @@ -16,16 +18,14 @@ import telegramium.bots.KeyboardMarkup * @param entities * A JSON-serialized list of special entities that appear in message text, which can be specified instead of * parse_mode - * @param disableWebPagePreview - * Disables link previews for links in this message + * @param linkPreviewOptions + * Link preview generation options for the message * @param disableNotification * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions * to remove reply keyboard or to force a reply from the user. @@ -36,10 +36,9 @@ final case class SendMessageReq( messageThreadId: Option[Int] = Option.empty, parseMode: Option[ParseMode] = Option.empty, entities: List[MessageEntity] = List.empty, - disableWebPagePreview: Option[Boolean] = Option.empty, + linkPreviewOptions: Option[LinkPreviewOptions] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendPhotoReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendPhotoReq.scala index d7af4404..83b670d7 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendPhotoReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendPhotoReq.scala @@ -4,6 +4,7 @@ import telegramium.bots.ChatId import telegramium.bots.IFile import telegramium.bots.ParseMode import telegramium.bots.MessageEntity +import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup /** @param chatId @@ -28,10 +29,8 @@ import telegramium.bots.KeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions * to remove reply keyboard or to force a reply from the user. @@ -46,7 +45,6 @@ final case class SendPhotoReq( hasSpoiler: Option[Boolean] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendPollReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendPollReq.scala index 84d6adcd..deaa74ca 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendPollReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendPollReq.scala @@ -1,7 +1,9 @@ package telegramium.bots.client import telegramium.bots.ChatId +import telegramium.bots.ParseMode import telegramium.bots.MessageEntity +import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup /** @param chatId @@ -39,10 +41,8 @@ import telegramium.bots.KeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions * to remove reply keyboard or to force a reply from the user. @@ -57,14 +57,13 @@ final case class SendPollReq( allowsMultipleAnswers: Option[Boolean] = Option.empty, correctOptionId: Option[Int] = Option.empty, explanation: Option[String] = Option.empty, - explanationParseMode: Option[String] = Option.empty, + explanationParseMode: Option[ParseMode] = Option.empty, explanationEntities: List[MessageEntity] = List.empty, openPeriod: Option[Int] = Option.empty, closeDate: Option[Int] = Option.empty, isClosed: Option[Boolean] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendStickerReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendStickerReq.scala index 09b7cae5..72c208d8 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendStickerReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendStickerReq.scala @@ -2,6 +2,7 @@ package telegramium.bots.client import telegramium.bots.ChatId import telegramium.bots.IFile +import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup /** @param chatId @@ -19,10 +20,8 @@ import telegramium.bots.KeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions * to remove reply keyboard or to force a reply from the user. @@ -34,7 +33,6 @@ final case class SendStickerReq( emoji: Option[String] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendVenueReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendVenueReq.scala index 2340592e..04a218d6 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendVenueReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendVenueReq.scala @@ -1,6 +1,7 @@ package telegramium.bots.client import telegramium.bots.ChatId +import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup /** @param chatId @@ -28,10 +29,8 @@ import telegramium.bots.KeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions * to remove reply keyboard or to force a reply from the user. @@ -49,7 +48,6 @@ final case class SendVenueReq( googlePlaceType: Option[String] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendVideoNoteReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendVideoNoteReq.scala index 96073e70..bad57056 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendVideoNoteReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendVideoNoteReq.scala @@ -2,6 +2,7 @@ package telegramium.bots.client import telegramium.bots.ChatId import telegramium.bots.IFile +import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup /** @param chatId @@ -26,10 +27,8 @@ import telegramium.bots.KeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions * to remove reply keyboard or to force a reply from the user. @@ -43,7 +42,6 @@ final case class SendVideoNoteReq( thumbnail: Option[IFile] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendVideoReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendVideoReq.scala index 84da2856..9da3b537 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendVideoReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendVideoReq.scala @@ -4,6 +4,7 @@ import telegramium.bots.ChatId import telegramium.bots.IFile import telegramium.bots.ParseMode import telegramium.bots.MessageEntity +import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup /** @param chatId @@ -41,10 +42,8 @@ import telegramium.bots.KeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions * to remove reply keyboard or to force a reply from the user. @@ -64,7 +63,6 @@ final case class SendVideoReq( supportsStreaming: Option[Boolean] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SendVoiceReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SendVoiceReq.scala index 7cf7e4ab..c6ad6d29 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SendVoiceReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SendVoiceReq.scala @@ -4,6 +4,7 @@ import telegramium.bots.ChatId import telegramium.bots.IFile import telegramium.bots.ParseMode import telegramium.bots.MessageEntity +import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup /** @param chatId @@ -27,10 +28,8 @@ import telegramium.bots.KeyboardMarkup * Sends the message silently. Users will receive a notification with no sound. * @param protectContent * Protects the contents of the sent message from forwarding and saving - * @param replyToMessageId - * If the message is a reply, ID of the original message - * @param allowSendingWithoutReply - * Pass True if the message should be sent even if the specified replied-to message is not found + * @param replyParameters + * Description of the message to reply to * @param replyMarkup * Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions * to remove reply keyboard or to force a reply from the user. @@ -45,7 +44,6 @@ final case class SendVoiceReq( duration: Option[Int] = Option.empty, disableNotification: Option[Boolean] = Option.empty, protectContent: Option[Boolean] = Option.empty, - replyToMessageId: Option[Int] = Option.empty, - allowSendingWithoutReply: Option[Boolean] = Option.empty, + replyParameters: Option[ReplyParameters] = Option.empty, replyMarkup: Option[KeyboardMarkup] = Option.empty ) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SetMessageReactionReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SetMessageReactionReq.scala new file mode 100644 index 00000000..f8ca9023 --- /dev/null +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SetMessageReactionReq.scala @@ -0,0 +1,22 @@ +package telegramium.bots.client + +import telegramium.bots.ChatId +import telegramium.bots.ReactionType + +/** @param chatId + * Unique identifier for the target chat or username of the target channel (in the format @channelusername) + * @param messageId + * Identifier of the target message + * @param reaction + * New list of reaction types to set on the message. Currently, as non-premium users, bots can set up to one reaction + * per message. A custom emoji reaction can be used if it is either already present on the message or explicitly + * allowed by chat administrators. + * @param isBig + * Pass True to set the reaction with a big animation + */ +final case class SetMessageReactionReq( + chatId: ChatId, + messageId: Int, + reaction: List[ReactionType] = List.empty, + isBig: Option[Boolean] = Option.empty +) diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/SetWebhookReq.scala b/telegramium-core/src/main/scala/telegramium/bots/client/SetWebhookReq.scala index 2056ce59..5347a1a1 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/SetWebhookReq.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/SetWebhookReq.scala @@ -14,11 +14,12 @@ import telegramium.bots.IFile * to 40. Use lower values to limit the load on your bot's server, and higher values to increase your bot's * throughput. * @param allowedUpdates - * A JSON-serialized list of the update types you want your bot to receive. For example, specify [“message”, - * “edited_channel_post”, “callback_query”] to only receive updates of these types. See Update for a complete list of - * available update types. Specify an empty list to receive all update types except chat_member (default). If not - * specified, the previous setting will be used. Please note that this parameter doesn't affect updates created - * before the call to the setWebhook, so unwanted updates may be received for a short period of time. + * A JSON-serialized list of the update types you want your bot to receive. For example, specify ["message", + * "edited_channel_post", "callback_query"] to only receive updates of these types. See Update for a complete list of + * available update types. Specify an empty list to receive all update types except chat_member, message_reaction, + * and message_reaction_count (default). If not specified, the previous setting will be used. Please note that this + * parameter doesn't affect updates created before the call to the setWebhook, so unwanted updates may be received + * for a short period of time. * @param dropPendingUpdates * Pass True to drop all pending updates * @param secretToken diff --git a/telegramium-core/src/main/scala/telegramium/bots/client/package.scala b/telegramium-core/src/main/scala/telegramium/bots/client/package.scala index 7fb53e25..3f83c91c 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/client/package.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/client/package.scala @@ -13,6 +13,8 @@ object CirceImplicits { import telegramium.bots.IFile import telegramium.bots.ParseMode import telegramium.bots.MessageEntity + import telegramium.bots.LinkPreviewOptions + import telegramium.bots.ReplyParameters import telegramium.bots.KeyboardMarkup import telegramium.bots.InlineQueryResult import telegramium.bots.InputSticker @@ -26,6 +28,7 @@ object CirceImplicits { import telegramium.bots.InlineQueryResultsButton import telegramium.bots.ChatAdministratorRights import telegramium.bots.ShippingOption + import telegramium.bots.ReactionType implicit lazy val responseEncoder: Encoder[Response] = (x: Response) => { @@ -111,6 +114,27 @@ object CirceImplicits { } } + implicit lazy val getuserchatboostsreqEncoder: Encoder[GetUserChatBoostsReq] = + (x: GetUserChatBoostsReq) => { + Json.fromFields( + List( + "chat_id" -> x.chatId.asJson, + "user_id" -> x.userId.asJson, + "method" -> "getUserChatBoosts".asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val getuserchatboostsreqDecoder: Decoder[GetUserChatBoostsReq] = + Decoder.instance { h => + for { + _chatId <- h.get[ChatId]("chat_id") + _userId <- h.get[Long]("user_id") + } yield { + GetUserChatBoostsReq(chatId = _chatId, userId = _userId) + } + } + implicit lazy val setchatphotoreqEncoder: Encoder[SetChatPhotoReq] = (x: SetChatPhotoReq) => { Json.fromFields( @@ -283,18 +307,17 @@ object CirceImplicits { (x: SendMessageReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "text" -> x.text.asJson, - "parse_mode" -> x.parseMode.asJson, - "entities" -> x.entities.asJson, - "disable_web_page_preview" -> x.disableWebPagePreview.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "sendMessage".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "text" -> x.text.asJson, + "parse_mode" -> x.parseMode.asJson, + "entities" -> x.entities.asJson, + "link_preview_options" -> x.linkPreviewOptions.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "sendMessage".asJson ).filter(!_._2.isNull) ) } @@ -302,17 +325,16 @@ object CirceImplicits { implicit lazy val sendmessagereqDecoder: Decoder[SendMessageReq] = Decoder.instance { h => for { - _chatId <- h.get[ChatId]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _text <- h.get[String]("text") - _parseMode <- h.get[Option[ParseMode]]("parse_mode") - _entities <- h.getOrElse[List[MessageEntity]]("entities")(List.empty) - _disableWebPagePreview <- h.get[Option[Boolean]]("disable_web_page_preview") - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") - _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _text <- h.get[String]("text") + _parseMode <- h.get[Option[ParseMode]]("parse_mode") + _entities <- h.getOrElse[List[MessageEntity]]("entities")(List.empty) + _linkPreviewOptions <- h.get[Option[LinkPreviewOptions]]("link_preview_options") + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") + _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") } yield { SendMessageReq( chatId = _chatId, @@ -320,11 +342,10 @@ object CirceImplicits { text = _text, parseMode = _parseMode, entities = _entities, - disableWebPagePreview = _disableWebPagePreview, + linkPreviewOptions = _linkPreviewOptions, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -357,26 +378,25 @@ object CirceImplicits { (x: SendPollReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "question" -> x.question.asJson, - "options" -> x.options.asJson, - "is_anonymous" -> x.isAnonymous.asJson, - "type" -> x.`type`.asJson, - "allows_multiple_answers" -> x.allowsMultipleAnswers.asJson, - "correct_option_id" -> x.correctOptionId.asJson, - "explanation" -> x.explanation.asJson, - "explanation_parse_mode" -> x.explanationParseMode.asJson, - "explanation_entities" -> x.explanationEntities.asJson, - "open_period" -> x.openPeriod.asJson, - "close_date" -> x.closeDate.asJson, - "is_closed" -> x.isClosed.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "sendPoll".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "question" -> x.question.asJson, + "options" -> x.options.asJson, + "is_anonymous" -> x.isAnonymous.asJson, + "type" -> x.`type`.asJson, + "allows_multiple_answers" -> x.allowsMultipleAnswers.asJson, + "correct_option_id" -> x.correctOptionId.asJson, + "explanation" -> x.explanation.asJson, + "explanation_parse_mode" -> x.explanationParseMode.asJson, + "explanation_entities" -> x.explanationEntities.asJson, + "open_period" -> x.openPeriod.asJson, + "close_date" -> x.closeDate.asJson, + "is_closed" -> x.isClosed.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "sendPoll".asJson ).filter(!_._2.isNull) ) } @@ -384,25 +404,24 @@ object CirceImplicits { implicit lazy val sendpollreqDecoder: Decoder[SendPollReq] = Decoder.instance { h => for { - _chatId <- h.get[ChatId]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _question <- h.get[String]("question") - _options <- h.getOrElse[List[String]]("options")(List.empty) - _isAnonymous <- h.get[Option[Boolean]]("is_anonymous") - _type <- h.get[Option[String]]("type") - _allowsMultipleAnswers <- h.get[Option[Boolean]]("allows_multiple_answers") - _correctOptionId <- h.get[Option[Int]]("correct_option_id") - _explanation <- h.get[Option[String]]("explanation") - _explanationParseMode <- h.get[Option[String]]("explanation_parse_mode") - _explanationEntities <- h.getOrElse[List[MessageEntity]]("explanation_entities")(List.empty) - _openPeriod <- h.get[Option[Int]]("open_period") - _closeDate <- h.get[Option[Int]]("close_date") - _isClosed <- h.get[Option[Boolean]]("is_closed") - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") - _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _question <- h.get[String]("question") + _options <- h.getOrElse[List[String]]("options")(List.empty) + _isAnonymous <- h.get[Option[Boolean]]("is_anonymous") + _type <- h.get[Option[String]]("type") + _allowsMultipleAnswers <- h.get[Option[Boolean]]("allows_multiple_answers") + _correctOptionId <- h.get[Option[Int]]("correct_option_id") + _explanation <- h.get[Option[String]]("explanation") + _explanationParseMode <- h.get[Option[ParseMode]]("explanation_parse_mode") + _explanationEntities <- h.getOrElse[List[MessageEntity]]("explanation_entities")(List.empty) + _openPeriod <- h.get[Option[Int]]("open_period") + _closeDate <- h.get[Option[Int]]("close_date") + _isClosed <- h.get[Option[Boolean]]("is_closed") + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") + _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") } yield { SendPollReq( chatId = _chatId, @@ -421,8 +440,7 @@ object CirceImplicits { isClosed = _isClosed, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -453,18 +471,17 @@ object CirceImplicits { (x: SendContactReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "phone_number" -> x.phoneNumber.asJson, - "first_name" -> x.firstName.asJson, - "last_name" -> x.lastName.asJson, - "vcard" -> x.vcard.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "sendContact".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "phone_number" -> x.phoneNumber.asJson, + "first_name" -> x.firstName.asJson, + "last_name" -> x.lastName.asJson, + "vcard" -> x.vcard.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "sendContact".asJson ).filter(!_._2.isNull) ) } @@ -472,17 +489,16 @@ object CirceImplicits { implicit lazy val sendcontactreqDecoder: Decoder[SendContactReq] = Decoder.instance { h => for { - _chatId <- h.get[ChatId]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _phoneNumber <- h.get[String]("phone_number") - _firstName <- h.get[String]("first_name") - _lastName <- h.get[Option[String]]("last_name") - _vcard <- h.get[Option[String]]("vcard") - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") - _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _phoneNumber <- h.get[String]("phone_number") + _firstName <- h.get[String]("first_name") + _lastName <- h.get[Option[String]]("last_name") + _vcard <- h.get[Option[String]]("vcard") + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") + _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") } yield { SendContactReq( chatId = _chatId, @@ -493,8 +509,7 @@ object CirceImplicits { vcard = _vcard, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -583,6 +598,27 @@ object CirceImplicits { } } + implicit lazy val deletemessagesreqEncoder: Encoder[DeleteMessagesReq] = + (x: DeleteMessagesReq) => { + Json.fromFields( + List( + "chat_id" -> x.chatId.asJson, + "message_ids" -> x.messageIds.asJson, + "method" -> "deleteMessages".asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val deletemessagesreqDecoder: Decoder[DeleteMessagesReq] = + Decoder.instance { h => + for { + _chatId <- h.get[ChatId]("chat_id") + _messageIds <- h.getOrElse[List[Int]]("message_ids")(List.empty) + } yield { + DeleteMessagesReq(chatId = _chatId, messageIds = _messageIds) + } + } + implicit lazy val setchatpermissionsreqEncoder: Encoder[SetChatPermissionsReq] = (x: SetChatPermissionsReq) => { Json.fromFields( @@ -656,20 +692,19 @@ object CirceImplicits { (x: SendLocationReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "latitude" -> x.latitude.asJson, - "longitude" -> x.longitude.asJson, - "horizontal_accuracy" -> x.horizontalAccuracy.asJson, - "live_period" -> x.livePeriod.asJson, - "heading" -> x.heading.asJson, - "proximity_alert_radius" -> x.proximityAlertRadius.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "sendLocation".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "latitude" -> x.latitude.asJson, + "longitude" -> x.longitude.asJson, + "horizontal_accuracy" -> x.horizontalAccuracy.asJson, + "live_period" -> x.livePeriod.asJson, + "heading" -> x.heading.asJson, + "proximity_alert_radius" -> x.proximityAlertRadius.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "sendLocation".asJson ).filter(!_._2.isNull) ) } @@ -677,19 +712,18 @@ object CirceImplicits { implicit lazy val sendlocationreqDecoder: Decoder[SendLocationReq] = Decoder.instance { h => for { - _chatId <- h.get[ChatId]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _latitude <- h.get[Float]("latitude") - _longitude <- h.get[Float]("longitude") - _horizontalAccuracy <- h.get[Option[Float]]("horizontal_accuracy") - _livePeriod <- h.get[Option[Int]]("live_period") - _heading <- h.get[Option[Int]]("heading") - _proximityAlertRadius <- h.get[Option[Int]]("proximity_alert_radius") - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") - _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _latitude <- h.get[Float]("latitude") + _longitude <- h.get[Float]("longitude") + _horizontalAccuracy <- h.get[Option[Float]]("horizontal_accuracy") + _livePeriod <- h.get[Option[Int]]("live_period") + _heading <- h.get[Option[Int]]("heading") + _proximityAlertRadius <- h.get[Option[Int]]("proximity_alert_radius") + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") + _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") } yield { SendLocationReq( chatId = _chatId, @@ -702,8 +736,7 @@ object CirceImplicits { proximityAlertRadius = _proximityAlertRadius, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -728,6 +761,45 @@ object CirceImplicits { } } + implicit lazy val copymessagesreqEncoder: Encoder[CopyMessagesReq] = + (x: CopyMessagesReq) => { + Json.fromFields( + List( + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "from_chat_id" -> x.fromChatId.asJson, + "message_ids" -> x.messageIds.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "remove_caption" -> x.removeCaption.asJson, + "method" -> "copyMessages".asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val copymessagesreqDecoder: Decoder[CopyMessagesReq] = + Decoder.instance { h => + for { + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _fromChatId <- h.get[ChatId]("from_chat_id") + _messageIds <- h.getOrElse[List[Int]]("message_ids")(List.empty) + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _removeCaption <- h.get[Option[Boolean]]("remove_caption") + } yield { + CopyMessagesReq( + chatId = _chatId, + messageThreadId = _messageThreadId, + fromChatId = _fromChatId, + messageIds = _messageIds, + disableNotification = _disableNotification, + protectContent = _protectContent, + removeCaption = _removeCaption + ) + } + } + implicit lazy val getmyshortdescriptionreqEncoder: Encoder[GetMyShortDescriptionReq] = (x: GetMyShortDescriptionReq) => { Json.fromFields( @@ -821,15 +893,14 @@ object CirceImplicits { (x: SendDiceReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "emoji" -> x.emoji.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "sendDice".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "emoji" -> x.emoji.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "sendDice".asJson ).filter(!_._2.isNull) ) } @@ -837,14 +908,13 @@ object CirceImplicits { implicit lazy val senddicereqDecoder: Decoder[SendDiceReq] = Decoder.instance { h => for { - _chatId <- h.get[ChatId]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _emoji <- h.get[Option[String]]("emoji") - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") - _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _emoji <- h.get[Option[String]]("emoji") + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") + _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") } yield { SendDiceReq( chatId = _chatId, @@ -852,8 +922,7 @@ object CirceImplicits { emoji = _emoji, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -1069,14 +1138,13 @@ object CirceImplicits { (x: SendMediaGroupReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "media" -> x.media.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "method" -> "sendMediaGroup".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "media" -> x.media.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "method" -> "sendMediaGroup".asJson ).filter(!_._2.isNull) ) } @@ -1084,13 +1152,12 @@ object CirceImplicits { implicit lazy val sendmediagroupreqDecoder: Decoder[SendMediaGroupReq] = Decoder.instance { h => for { - _chatId <- h.get[ChatId]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _media <- h.getOrElse[List[InputMedia]]("media")(List.empty) - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _media <- h.getOrElse[List[InputMedia]]("media")(List.empty) + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") } yield { SendMediaGroupReq( chatId = _chatId, @@ -1098,8 +1165,7 @@ object CirceImplicits { media = _media, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply + replyParameters = _replyParameters ) } } @@ -1108,15 +1174,14 @@ object CirceImplicits { (x: SendGameReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "game_short_name" -> x.gameShortName.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "sendGame".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "game_short_name" -> x.gameShortName.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "sendGame".asJson ).filter(!_._2.isNull) ) } @@ -1124,14 +1189,13 @@ object CirceImplicits { implicit lazy val sendgamereqDecoder: Decoder[SendGameReq] = Decoder.instance { h => for { - _chatId <- h.get[Long]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _gameShortName <- h.get[String]("game_short_name") - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") - _replyMarkup <- h.get[Option[InlineKeyboardMarkup]]("reply_markup") + _chatId <- h.get[Long]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _gameShortName <- h.get[String]("game_short_name") + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") + _replyMarkup <- h.get[Option[InlineKeyboardMarkup]]("reply_markup") } yield { SendGameReq( chatId = _chatId, @@ -1139,8 +1203,7 @@ object CirceImplicits { gameShortName = _gameShortName, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -1150,22 +1213,21 @@ object CirceImplicits { (x: SendVenueReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "latitude" -> x.latitude.asJson, - "longitude" -> x.longitude.asJson, - "title" -> x.title.asJson, - "address" -> x.address.asJson, - "foursquare_id" -> x.foursquareId.asJson, - "foursquare_type" -> x.foursquareType.asJson, - "google_place_id" -> x.googlePlaceId.asJson, - "google_place_type" -> x.googlePlaceType.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "sendVenue".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "latitude" -> x.latitude.asJson, + "longitude" -> x.longitude.asJson, + "title" -> x.title.asJson, + "address" -> x.address.asJson, + "foursquare_id" -> x.foursquareId.asJson, + "foursquare_type" -> x.foursquareType.asJson, + "google_place_id" -> x.googlePlaceId.asJson, + "google_place_type" -> x.googlePlaceType.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "sendVenue".asJson ).filter(!_._2.isNull) ) } @@ -1173,21 +1235,20 @@ object CirceImplicits { implicit lazy val sendvenuereqDecoder: Decoder[SendVenueReq] = Decoder.instance { h => for { - _chatId <- h.get[ChatId]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _latitude <- h.get[Float]("latitude") - _longitude <- h.get[Float]("longitude") - _title <- h.get[String]("title") - _address <- h.get[String]("address") - _foursquareId <- h.get[Option[String]]("foursquare_id") - _foursquareType <- h.get[Option[String]]("foursquare_type") - _googlePlaceId <- h.get[Option[String]]("google_place_id") - _googlePlaceType <- h.get[Option[String]]("google_place_type") - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") - _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _latitude <- h.get[Float]("latitude") + _longitude <- h.get[Float]("longitude") + _title <- h.get[String]("title") + _address <- h.get[String]("address") + _foursquareId <- h.get[Option[String]]("foursquare_id") + _foursquareType <- h.get[Option[String]]("foursquare_type") + _googlePlaceId <- h.get[Option[String]]("google_place_id") + _googlePlaceType <- h.get[Option[String]]("google_place_type") + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") + _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") } yield { SendVenueReq( chatId = _chatId, @@ -1202,8 +1263,7 @@ object CirceImplicits { googlePlaceType = _googlePlaceType, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -1348,15 +1408,15 @@ object CirceImplicits { (x: EditMessageTextReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_id" -> x.messageId.asJson, - "inline_message_id" -> x.inlineMessageId.asJson, - "text" -> x.text.asJson, - "parse_mode" -> x.parseMode.asJson, - "entities" -> x.entities.asJson, - "disable_web_page_preview" -> x.disableWebPagePreview.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "editMessageText".asJson + "chat_id" -> x.chatId.asJson, + "message_id" -> x.messageId.asJson, + "inline_message_id" -> x.inlineMessageId.asJson, + "text" -> x.text.asJson, + "parse_mode" -> x.parseMode.asJson, + "entities" -> x.entities.asJson, + "link_preview_options" -> x.linkPreviewOptions.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "editMessageText".asJson ).filter(!_._2.isNull) ) } @@ -1364,14 +1424,14 @@ object CirceImplicits { implicit lazy val editmessagetextreqDecoder: Decoder[EditMessageTextReq] = Decoder.instance { h => for { - _chatId <- h.get[Option[ChatId]]("chat_id") - _messageId <- h.get[Option[Int]]("message_id") - _inlineMessageId <- h.get[Option[String]]("inline_message_id") - _text <- h.get[String]("text") - _parseMode <- h.get[Option[ParseMode]]("parse_mode") - _entities <- h.getOrElse[List[MessageEntity]]("entities")(List.empty) - _disableWebPagePreview <- h.get[Option[Boolean]]("disable_web_page_preview") - _replyMarkup <- h.get[Option[InlineKeyboardMarkup]]("reply_markup") + _chatId <- h.get[Option[ChatId]]("chat_id") + _messageId <- h.get[Option[Int]]("message_id") + _inlineMessageId <- h.get[Option[String]]("inline_message_id") + _text <- h.get[String]("text") + _parseMode <- h.get[Option[ParseMode]]("parse_mode") + _entities <- h.getOrElse[List[MessageEntity]]("entities")(List.empty) + _linkPreviewOptions <- h.get[Option[LinkPreviewOptions]]("link_preview_options") + _replyMarkup <- h.get[Option[InlineKeyboardMarkup]]("reply_markup") } yield { EditMessageTextReq( chatId = _chatId, @@ -1380,7 +1440,7 @@ object CirceImplicits { text = _text, parseMode = _parseMode, entities = _entities, - disableWebPagePreview = _disableWebPagePreview, + linkPreviewOptions = _linkPreviewOptions, replyMarkup = _replyMarkup ) } @@ -1573,19 +1633,18 @@ object CirceImplicits { (x: CopyMessageReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "from_chat_id" -> x.fromChatId.asJson, - "message_id" -> x.messageId.asJson, - "caption" -> x.caption.asJson, - "parse_mode" -> x.parseMode.asJson, - "caption_entities" -> x.captionEntities.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "copyMessage".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "from_chat_id" -> x.fromChatId.asJson, + "message_id" -> x.messageId.asJson, + "caption" -> x.caption.asJson, + "parse_mode" -> x.parseMode.asJson, + "caption_entities" -> x.captionEntities.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "copyMessage".asJson ).filter(!_._2.isNull) ) } @@ -1593,18 +1652,17 @@ object CirceImplicits { implicit lazy val copymessagereqDecoder: Decoder[CopyMessageReq] = Decoder.instance { h => for { - _chatId <- h.get[ChatId]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _fromChatId <- h.get[ChatId]("from_chat_id") - _messageId <- h.get[Int]("message_id") - _caption <- h.get[Option[String]]("caption") - _parseMode <- h.get[Option[ParseMode]]("parse_mode") - _captionEntities <- h.getOrElse[List[MessageEntity]]("caption_entities")(List.empty) - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") - _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _fromChatId <- h.get[ChatId]("from_chat_id") + _messageId <- h.get[Int]("message_id") + _caption <- h.get[Option[String]]("caption") + _parseMode <- h.get[Option[ParseMode]]("parse_mode") + _captionEntities <- h.getOrElse[List[MessageEntity]]("caption_entities")(List.empty) + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") + _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") } yield { CopyMessageReq( chatId = _chatId, @@ -1616,8 +1674,7 @@ object CirceImplicits { captionEntities = _captionEntities, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -1627,18 +1684,17 @@ object CirceImplicits { (x: SendVideoNoteReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "video_note" -> x.videoNote.asJson, - "duration" -> x.duration.asJson, - "length" -> x.length.asJson, - "thumbnail" -> x.thumbnail.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "sendVideoNote".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "video_note" -> x.videoNote.asJson, + "duration" -> x.duration.asJson, + "length" -> x.length.asJson, + "thumbnail" -> x.thumbnail.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "sendVideoNote".asJson ).filter(!_._2.isNull) ) } @@ -1646,17 +1702,16 @@ object CirceImplicits { implicit lazy val sendvideonotereqDecoder: Decoder[SendVideoNoteReq] = Decoder.instance { h => for { - _chatId <- h.get[ChatId]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _videoNote <- h.get[IFile]("video_note") - _duration <- h.get[Option[Int]]("duration") - _length <- h.get[Option[Int]]("length") - _thumbnail <- h.get[Option[IFile]]("thumbnail") - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") - _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _videoNote <- h.get[IFile]("video_note") + _duration <- h.get[Option[Int]]("duration") + _length <- h.get[Option[Int]]("length") + _thumbnail <- h.get[Option[IFile]]("thumbnail") + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") + _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") } yield { SendVideoNoteReq( chatId = _chatId, @@ -1667,8 +1722,7 @@ object CirceImplicits { thumbnail = _thumbnail, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -1800,8 +1854,7 @@ object CirceImplicits { "is_flexible" -> x.isFlexible.asJson, "disable_notification" -> x.disableNotification.asJson, "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, + "reply_parameters" -> x.replyParameters.asJson, "reply_markup" -> x.replyMarkup.asJson, "method" -> "sendInvoice".asJson ).filter(!_._2.isNull) @@ -1836,8 +1889,7 @@ object CirceImplicits { _isFlexible <- h.get[Option[Boolean]]("is_flexible") _disableNotification <- h.get[Option[Boolean]]("disable_notification") _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") _replyMarkup <- h.get[Option[InlineKeyboardMarkup]]("reply_markup") } yield { SendInvoiceReq( @@ -1866,8 +1918,7 @@ object CirceImplicits { isFlexible = _isFlexible, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -1908,8 +1959,7 @@ object CirceImplicits { "disable_content_type_detection" -> x.disableContentTypeDetection.asJson, "disable_notification" -> x.disableNotification.asJson, "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, + "reply_parameters" -> x.replyParameters.asJson, "reply_markup" -> x.replyMarkup.asJson, "method" -> "sendDocument".asJson ).filter(!_._2.isNull) @@ -1929,8 +1979,7 @@ object CirceImplicits { _disableContentTypeDetection <- h.get[Option[Boolean]]("disable_content_type_detection") _disableNotification <- h.get[Option[Boolean]]("disable_notification") _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") } yield { SendDocumentReq( @@ -1944,8 +1993,7 @@ object CirceImplicits { disableContentTypeDetection = _disableContentTypeDetection, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -2052,22 +2100,21 @@ object CirceImplicits { (x: SendAudioReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "audio" -> x.audio.asJson, - "caption" -> x.caption.asJson, - "parse_mode" -> x.parseMode.asJson, - "caption_entities" -> x.captionEntities.asJson, - "duration" -> x.duration.asJson, - "performer" -> x.performer.asJson, - "title" -> x.title.asJson, - "thumbnail" -> x.thumbnail.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "sendAudio".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "audio" -> x.audio.asJson, + "caption" -> x.caption.asJson, + "parse_mode" -> x.parseMode.asJson, + "caption_entities" -> x.captionEntities.asJson, + "duration" -> x.duration.asJson, + "performer" -> x.performer.asJson, + "title" -> x.title.asJson, + "thumbnail" -> x.thumbnail.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "sendAudio".asJson ).filter(!_._2.isNull) ) } @@ -2075,21 +2122,20 @@ object CirceImplicits { implicit lazy val sendaudioreqDecoder: Decoder[SendAudioReq] = Decoder.instance { h => for { - _chatId <- h.get[ChatId]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _audio <- h.get[IFile]("audio") - _caption <- h.get[Option[String]]("caption") - _parseMode <- h.get[Option[ParseMode]]("parse_mode") - _captionEntities <- h.getOrElse[List[MessageEntity]]("caption_entities")(List.empty) - _duration <- h.get[Option[Int]]("duration") - _performer <- h.get[Option[String]]("performer") - _title <- h.get[Option[String]]("title") - _thumbnail <- h.get[Option[IFile]]("thumbnail") - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") - _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _audio <- h.get[IFile]("audio") + _caption <- h.get[Option[String]]("caption") + _parseMode <- h.get[Option[ParseMode]]("parse_mode") + _captionEntities <- h.getOrElse[List[MessageEntity]]("caption_entities")(List.empty) + _duration <- h.get[Option[Int]]("duration") + _performer <- h.get[Option[String]]("performer") + _title <- h.get[Option[String]]("title") + _thumbnail <- h.get[Option[IFile]]("thumbnail") + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") + _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") } yield { SendAudioReq( chatId = _chatId, @@ -2104,8 +2150,7 @@ object CirceImplicits { thumbnail = _thumbnail, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -2294,19 +2339,18 @@ object CirceImplicits { (x: SendVoiceReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "voice" -> x.voice.asJson, - "caption" -> x.caption.asJson, - "parse_mode" -> x.parseMode.asJson, - "caption_entities" -> x.captionEntities.asJson, - "duration" -> x.duration.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "sendVoice".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "voice" -> x.voice.asJson, + "caption" -> x.caption.asJson, + "parse_mode" -> x.parseMode.asJson, + "caption_entities" -> x.captionEntities.asJson, + "duration" -> x.duration.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "sendVoice".asJson ).filter(!_._2.isNull) ) } @@ -2314,18 +2358,17 @@ object CirceImplicits { implicit lazy val sendvoicereqDecoder: Decoder[SendVoiceReq] = Decoder.instance { h => for { - _chatId <- h.get[ChatId]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _voice <- h.get[IFile]("voice") - _caption <- h.get[Option[String]]("caption") - _parseMode <- h.get[Option[ParseMode]]("parse_mode") - _captionEntities <- h.getOrElse[List[MessageEntity]]("caption_entities")(List.empty) - _duration <- h.get[Option[Int]]("duration") - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") - _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _voice <- h.get[IFile]("voice") + _caption <- h.get[Option[String]]("caption") + _parseMode <- h.get[Option[ParseMode]]("parse_mode") + _captionEntities <- h.getOrElse[List[MessageEntity]]("caption_entities")(List.empty) + _duration <- h.get[Option[Int]]("duration") + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") + _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") } yield { SendVoiceReq( chatId = _chatId, @@ -2337,8 +2380,7 @@ object CirceImplicits { duration = _duration, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -2355,18 +2397,18 @@ object CirceImplicits { "user_id" -> x.userId.asJson, "is_anonymous" -> x.isAnonymous.asJson, "can_manage_chat" -> x.canManageChat.asJson, - "can_post_messages" -> x.canPostMessages.asJson, - "can_edit_messages" -> x.canEditMessages.asJson, "can_delete_messages" -> x.canDeleteMessages.asJson, - "can_post_stories" -> x.canPostStories.asJson, - "can_edit_stories" -> x.canEditStories.asJson, - "can_delete_stories" -> x.canDeleteStories.asJson, "can_manage_video_chats" -> x.canManageVideoChats.asJson, "can_restrict_members" -> x.canRestrictMembers.asJson, "can_promote_members" -> x.canPromoteMembers.asJson, "can_change_info" -> x.canChangeInfo.asJson, "can_invite_users" -> x.canInviteUsers.asJson, + "can_post_messages" -> x.canPostMessages.asJson, + "can_edit_messages" -> x.canEditMessages.asJson, "can_pin_messages" -> x.canPinMessages.asJson, + "can_post_stories" -> x.canPostStories.asJson, + "can_edit_stories" -> x.canEditStories.asJson, + "can_delete_stories" -> x.canDeleteStories.asJson, "can_manage_topics" -> x.canManageTopics.asJson, "method" -> "promoteChatMember".asJson ).filter(!_._2.isNull) @@ -2380,18 +2422,18 @@ object CirceImplicits { _userId <- h.get[Long]("user_id") _isAnonymous <- h.get[Option[Boolean]]("is_anonymous") _canManageChat <- h.get[Option[Boolean]]("can_manage_chat") - _canPostMessages <- h.get[Option[Boolean]]("can_post_messages") - _canEditMessages <- h.get[Option[Boolean]]("can_edit_messages") _canDeleteMessages <- h.get[Option[Boolean]]("can_delete_messages") - _canPostStories <- h.get[Option[Boolean]]("can_post_stories") - _canEditStories <- h.get[Option[Boolean]]("can_edit_stories") - _canDeleteStories <- h.get[Option[Boolean]]("can_delete_stories") _canManageVideoChats <- h.get[Option[Boolean]]("can_manage_video_chats") _canRestrictMembers <- h.get[Option[Boolean]]("can_restrict_members") _canPromoteMembers <- h.get[Option[Boolean]]("can_promote_members") _canChangeInfo <- h.get[Option[Boolean]]("can_change_info") _canInviteUsers <- h.get[Option[Boolean]]("can_invite_users") + _canPostMessages <- h.get[Option[Boolean]]("can_post_messages") + _canEditMessages <- h.get[Option[Boolean]]("can_edit_messages") _canPinMessages <- h.get[Option[Boolean]]("can_pin_messages") + _canPostStories <- h.get[Option[Boolean]]("can_post_stories") + _canEditStories <- h.get[Option[Boolean]]("can_edit_stories") + _canDeleteStories <- h.get[Option[Boolean]]("can_delete_stories") _canManageTopics <- h.get[Option[Boolean]]("can_manage_topics") } yield { PromoteChatMemberReq( @@ -2399,18 +2441,18 @@ object CirceImplicits { userId = _userId, isAnonymous = _isAnonymous, canManageChat = _canManageChat, - canPostMessages = _canPostMessages, - canEditMessages = _canEditMessages, canDeleteMessages = _canDeleteMessages, - canPostStories = _canPostStories, - canEditStories = _canEditStories, - canDeleteStories = _canDeleteStories, canManageVideoChats = _canManageVideoChats, canRestrictMembers = _canRestrictMembers, canPromoteMembers = _canPromoteMembers, canChangeInfo = _canChangeInfo, canInviteUsers = _canInviteUsers, + canPostMessages = _canPostMessages, + canEditMessages = _canEditMessages, canPinMessages = _canPinMessages, + canPostStories = _canPostStories, + canEditStories = _canEditStories, + canDeleteStories = _canDeleteStories, canManageTopics = _canManageTopics ) } @@ -2658,24 +2700,23 @@ object CirceImplicits { (x: SendVideoReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "video" -> x.video.asJson, - "duration" -> x.duration.asJson, - "width" -> x.width.asJson, - "height" -> x.height.asJson, - "thumbnail" -> x.thumbnail.asJson, - "caption" -> x.caption.asJson, - "parse_mode" -> x.parseMode.asJson, - "caption_entities" -> x.captionEntities.asJson, - "has_spoiler" -> x.hasSpoiler.asJson, - "supports_streaming" -> x.supportsStreaming.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "sendVideo".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "video" -> x.video.asJson, + "duration" -> x.duration.asJson, + "width" -> x.width.asJson, + "height" -> x.height.asJson, + "thumbnail" -> x.thumbnail.asJson, + "caption" -> x.caption.asJson, + "parse_mode" -> x.parseMode.asJson, + "caption_entities" -> x.captionEntities.asJson, + "has_spoiler" -> x.hasSpoiler.asJson, + "supports_streaming" -> x.supportsStreaming.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "sendVideo".asJson ).filter(!_._2.isNull) ) } @@ -2683,23 +2724,22 @@ object CirceImplicits { implicit lazy val sendvideoreqDecoder: Decoder[SendVideoReq] = Decoder.instance { h => for { - _chatId <- h.get[ChatId]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _video <- h.get[IFile]("video") - _duration <- h.get[Option[Int]]("duration") - _width <- h.get[Option[Int]]("width") - _height <- h.get[Option[Int]]("height") - _thumbnail <- h.get[Option[IFile]]("thumbnail") - _caption <- h.get[Option[String]]("caption") - _parseMode <- h.get[Option[ParseMode]]("parse_mode") - _captionEntities <- h.getOrElse[List[MessageEntity]]("caption_entities")(List.empty) - _hasSpoiler <- h.get[Option[Boolean]]("has_spoiler") - _supportsStreaming <- h.get[Option[Boolean]]("supports_streaming") - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") - _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _video <- h.get[IFile]("video") + _duration <- h.get[Option[Int]]("duration") + _width <- h.get[Option[Int]]("width") + _height <- h.get[Option[Int]]("height") + _thumbnail <- h.get[Option[IFile]]("thumbnail") + _caption <- h.get[Option[String]]("caption") + _parseMode <- h.get[Option[ParseMode]]("parse_mode") + _captionEntities <- h.getOrElse[List[MessageEntity]]("caption_entities")(List.empty) + _hasSpoiler <- h.get[Option[Boolean]]("has_spoiler") + _supportsStreaming <- h.get[Option[Boolean]]("supports_streaming") + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") + _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") } yield { SendVideoReq( chatId = _chatId, @@ -2716,8 +2756,7 @@ object CirceImplicits { supportsStreaming = _supportsStreaming, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -2913,23 +2952,22 @@ object CirceImplicits { (x: SendAnimationReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "animation" -> x.animation.asJson, - "duration" -> x.duration.asJson, - "width" -> x.width.asJson, - "height" -> x.height.asJson, - "thumbnail" -> x.thumbnail.asJson, - "caption" -> x.caption.asJson, - "parse_mode" -> x.parseMode.asJson, - "caption_entities" -> x.captionEntities.asJson, - "has_spoiler" -> x.hasSpoiler.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "sendAnimation".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "animation" -> x.animation.asJson, + "duration" -> x.duration.asJson, + "width" -> x.width.asJson, + "height" -> x.height.asJson, + "thumbnail" -> x.thumbnail.asJson, + "caption" -> x.caption.asJson, + "parse_mode" -> x.parseMode.asJson, + "caption_entities" -> x.captionEntities.asJson, + "has_spoiler" -> x.hasSpoiler.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "sendAnimation".asJson ).filter(!_._2.isNull) ) } @@ -2937,22 +2975,21 @@ object CirceImplicits { implicit lazy val sendanimationreqDecoder: Decoder[SendAnimationReq] = Decoder.instance { h => for { - _chatId <- h.get[ChatId]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _animation <- h.get[IFile]("animation") - _duration <- h.get[Option[Int]]("duration") - _width <- h.get[Option[Int]]("width") - _height <- h.get[Option[Int]]("height") - _thumbnail <- h.get[Option[IFile]]("thumbnail") - _caption <- h.get[Option[String]]("caption") - _parseMode <- h.get[Option[ParseMode]]("parse_mode") - _captionEntities <- h.getOrElse[List[MessageEntity]]("caption_entities")(List.empty) - _hasSpoiler <- h.get[Option[Boolean]]("has_spoiler") - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") - _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _animation <- h.get[IFile]("animation") + _duration <- h.get[Option[Int]]("duration") + _width <- h.get[Option[Int]]("width") + _height <- h.get[Option[Int]]("height") + _thumbnail <- h.get[Option[IFile]]("thumbnail") + _caption <- h.get[Option[String]]("caption") + _parseMode <- h.get[Option[ParseMode]]("parse_mode") + _captionEntities <- h.getOrElse[List[MessageEntity]]("caption_entities")(List.empty) + _hasSpoiler <- h.get[Option[Boolean]]("has_spoiler") + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") + _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") } yield { SendAnimationReq( chatId = _chatId, @@ -2968,8 +3005,7 @@ object CirceImplicits { hasSpoiler = _hasSpoiler, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -3097,16 +3133,15 @@ object CirceImplicits { (x: SendStickerReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "sticker" -> x.sticker.asJson, - "emoji" -> x.emoji.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "sendSticker".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "sticker" -> x.sticker.asJson, + "emoji" -> x.emoji.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "sendSticker".asJson ).filter(!_._2.isNull) ) } @@ -3114,15 +3149,14 @@ object CirceImplicits { implicit lazy val sendstickerreqDecoder: Decoder[SendStickerReq] = Decoder.instance { h => for { - _chatId <- h.get[ChatId]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _sticker <- h.get[IFile]("sticker") - _emoji <- h.get[Option[String]]("emoji") - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") - _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _sticker <- h.get[IFile]("sticker") + _emoji <- h.get[Option[String]]("emoji") + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") + _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") } yield { SendStickerReq( chatId = _chatId, @@ -3131,8 +3165,7 @@ object CirceImplicits { emoji = _emoji, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -3210,23 +3243,58 @@ object CirceImplicits { } } + implicit lazy val forwardmessagesreqEncoder: Encoder[ForwardMessagesReq] = + (x: ForwardMessagesReq) => { + Json.fromFields( + List( + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "from_chat_id" -> x.fromChatId.asJson, + "message_ids" -> x.messageIds.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "method" -> "forwardMessages".asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val forwardmessagesreqDecoder: Decoder[ForwardMessagesReq] = + Decoder.instance { h => + for { + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _fromChatId <- h.get[ChatId]("from_chat_id") + _messageIds <- h.getOrElse[List[Int]]("message_ids")(List.empty) + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + } yield { + ForwardMessagesReq( + chatId = _chatId, + messageThreadId = _messageThreadId, + fromChatId = _fromChatId, + messageIds = _messageIds, + disableNotification = _disableNotification, + protectContent = _protectContent + ) + } + } + implicit lazy val sendphotoreqEncoder: Encoder[SendPhotoReq] = (x: SendPhotoReq) => { Json.fromFields( List( - "chat_id" -> x.chatId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "photo" -> x.photo.asJson, - "caption" -> x.caption.asJson, - "parse_mode" -> x.parseMode.asJson, - "caption_entities" -> x.captionEntities.asJson, - "has_spoiler" -> x.hasSpoiler.asJson, - "disable_notification" -> x.disableNotification.asJson, - "protect_content" -> x.protectContent.asJson, - "reply_to_message_id" -> x.replyToMessageId.asJson, - "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, - "reply_markup" -> x.replyMarkup.asJson, - "method" -> "sendPhoto".asJson + "chat_id" -> x.chatId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "photo" -> x.photo.asJson, + "caption" -> x.caption.asJson, + "parse_mode" -> x.parseMode.asJson, + "caption_entities" -> x.captionEntities.asJson, + "has_spoiler" -> x.hasSpoiler.asJson, + "disable_notification" -> x.disableNotification.asJson, + "protect_content" -> x.protectContent.asJson, + "reply_parameters" -> x.replyParameters.asJson, + "reply_markup" -> x.replyMarkup.asJson, + "method" -> "sendPhoto".asJson ).filter(!_._2.isNull) ) } @@ -3234,18 +3302,17 @@ object CirceImplicits { implicit lazy val sendphotoreqDecoder: Decoder[SendPhotoReq] = Decoder.instance { h => for { - _chatId <- h.get[ChatId]("chat_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _photo <- h.get[IFile]("photo") - _caption <- h.get[Option[String]]("caption") - _parseMode <- h.get[Option[ParseMode]]("parse_mode") - _captionEntities <- h.getOrElse[List[MessageEntity]]("caption_entities")(List.empty) - _hasSpoiler <- h.get[Option[Boolean]]("has_spoiler") - _disableNotification <- h.get[Option[Boolean]]("disable_notification") - _protectContent <- h.get[Option[Boolean]]("protect_content") - _replyToMessageId <- h.get[Option[Int]]("reply_to_message_id") - _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") - _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") + _chatId <- h.get[ChatId]("chat_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _photo <- h.get[IFile]("photo") + _caption <- h.get[Option[String]]("caption") + _parseMode <- h.get[Option[ParseMode]]("parse_mode") + _captionEntities <- h.getOrElse[List[MessageEntity]]("caption_entities")(List.empty) + _hasSpoiler <- h.get[Option[Boolean]]("has_spoiler") + _disableNotification <- h.get[Option[Boolean]]("disable_notification") + _protectContent <- h.get[Option[Boolean]]("protect_content") + _replyParameters <- h.get[Option[ReplyParameters]]("reply_parameters") + _replyMarkup <- h.get[Option[KeyboardMarkup]]("reply_markup") } yield { SendPhotoReq( chatId = _chatId, @@ -3257,8 +3324,7 @@ object CirceImplicits { hasSpoiler = _hasSpoiler, disableNotification = _disableNotification, protectContent = _protectContent, - replyToMessageId = _replyToMessageId, - allowSendingWithoutReply = _allowSendingWithoutReply, + replyParameters = _replyParameters, replyMarkup = _replyMarkup ) } @@ -3368,4 +3434,29 @@ object CirceImplicits { } } + implicit lazy val setmessagereactionreqEncoder: Encoder[SetMessageReactionReq] = + (x: SetMessageReactionReq) => { + Json.fromFields( + List( + "chat_id" -> x.chatId.asJson, + "message_id" -> x.messageId.asJson, + "reaction" -> x.reaction.asJson, + "is_big" -> x.isBig.asJson, + "method" -> "setMessageReaction".asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val setmessagereactionreqDecoder: Decoder[SetMessageReactionReq] = + Decoder.instance { h => + for { + _chatId <- h.get[ChatId]("chat_id") + _messageId <- h.get[Int]("message_id") + _reaction <- h.getOrElse[List[ReactionType]]("reaction")(List.empty) + _isBig <- h.get[Option[Boolean]]("is_big") + } yield { + SetMessageReactionReq(chatId = _chatId, messageId = _messageId, reaction = _reaction, isBig = _isBig) + } + } + } diff --git a/telegramium-core/src/main/scala/telegramium/bots/package.scala b/telegramium-core/src/main/scala/telegramium/bots/package.scala index 74b352c5..08f1ab0d 100644 --- a/telegramium-core/src/main/scala/telegramium/bots/package.scala +++ b/telegramium-core/src/main/scala/telegramium/bots/package.scala @@ -210,6 +210,397 @@ object CirceImplicits { implicit lazy val inputlinkfileEncoder: Encoder[InputLinkFile] = (x: InputLinkFile) => x.file.asJson implicit lazy val inputlinkfileDecoder: Decoder[InputLinkFile] = Decoder[String].map(InputLinkFile.apply) + implicit lazy val maybeinaccessiblemessageEncoder: Encoder[MaybeInaccessibleMessage] = { + case x: Message => x.asJson + case x: InaccessibleMessage => x.asJson + } + + implicit lazy val maybeinaccessiblemessageDecoder: Decoder[MaybeInaccessibleMessage] = { + List[Decoder[MaybeInaccessibleMessage]]( + messageDecoder.widen, + inaccessiblemessageDecoder.widen + ).reduceLeft(_ or _) + } + + implicit lazy val messageEncoder: Encoder[Message] = + (x: Message) => { + Json.fromFields( + List( + "message_id" -> x.messageId.asJson, + "message_thread_id" -> x.messageThreadId.asJson, + "from" -> x.from.asJson, + "sender_chat" -> x.senderChat.asJson, + "date" -> x.date.asJson, + "chat" -> x.chat.asJson, + "forward_origin" -> x.forwardOrigin.asJson, + "is_topic_message" -> x.isTopicMessage.asJson, + "is_automatic_forward" -> x.isAutomaticForward.asJson, + "reply_to_message" -> x.replyToMessage.asJson, + "external_reply" -> x.externalReply.asJson, + "quote" -> x.quote.asJson, + "via_bot" -> x.viaBot.asJson, + "edit_date" -> x.editDate.asJson, + "has_protected_content" -> x.hasProtectedContent.asJson, + "media_group_id" -> x.mediaGroupId.asJson, + "author_signature" -> x.authorSignature.asJson, + "text" -> x.text.asJson, + "entities" -> x.entities.asJson, + "link_preview_options" -> x.linkPreviewOptions.asJson, + "animation" -> x.animation.asJson, + "audio" -> x.audio.asJson, + "document" -> x.document.asJson, + "photo" -> x.photo.asJson, + "sticker" -> x.sticker.asJson, + "story" -> x.story.asJson, + "video" -> x.video.asJson, + "video_note" -> x.videoNote.asJson, + "voice" -> x.voice.asJson, + "caption" -> x.caption.asJson, + "caption_entities" -> x.captionEntities.asJson, + "has_media_spoiler" -> x.hasMediaSpoiler.asJson, + "contact" -> x.contact.asJson, + "dice" -> x.dice.asJson, + "game" -> x.game.asJson, + "poll" -> x.poll.asJson, + "venue" -> x.venue.asJson, + "location" -> x.location.asJson, + "new_chat_members" -> x.newChatMembers.asJson, + "left_chat_member" -> x.leftChatMember.asJson, + "new_chat_title" -> x.newChatTitle.asJson, + "new_chat_photo" -> x.newChatPhoto.asJson, + "delete_chat_photo" -> x.deleteChatPhoto.asJson, + "group_chat_created" -> x.groupChatCreated.asJson, + "supergroup_chat_created" -> x.supergroupChatCreated.asJson, + "channel_chat_created" -> x.channelChatCreated.asJson, + "message_auto_delete_timer_changed" -> x.messageAutoDeleteTimerChanged.asJson, + "migrate_to_chat_id" -> x.migrateToChatId.asJson, + "migrate_from_chat_id" -> x.migrateFromChatId.asJson, + "pinned_message" -> x.pinnedMessage.asJson, + "invoice" -> x.invoice.asJson, + "successful_payment" -> x.successfulPayment.asJson, + "users_shared" -> x.usersShared.asJson, + "chat_shared" -> x.chatShared.asJson, + "connected_website" -> x.connectedWebsite.asJson, + "write_access_allowed" -> x.writeAccessAllowed.asJson, + "passport_data" -> x.passportData.asJson, + "proximity_alert_triggered" -> x.proximityAlertTriggered.asJson, + "forum_topic_created" -> x.forumTopicCreated.asJson, + "forum_topic_edited" -> x.forumTopicEdited.asJson, + "forum_topic_closed" -> x.forumTopicClosed.asJson, + "forum_topic_reopened" -> x.forumTopicReopened.asJson, + "general_forum_topic_hidden" -> x.generalForumTopicHidden.asJson, + "general_forum_topic_unhidden" -> x.generalForumTopicUnhidden.asJson, + "giveaway_created" -> x.giveawayCreated.asJson, + "giveaway" -> x.giveaway.asJson, + "giveaway_winners" -> x.giveawayWinners.asJson, + "giveaway_completed" -> x.giveawayCompleted.asJson, + "video_chat_scheduled" -> x.videoChatScheduled.asJson, + "video_chat_started" -> x.videoChatStarted.asJson, + "video_chat_ended" -> x.videoChatEnded.asJson, + "video_chat_participants_invited" -> x.videoChatParticipantsInvited.asJson, + "web_app_data" -> x.webAppData.asJson, + "reply_markup" -> x.replyMarkup.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val messageDecoder: Decoder[Message] = + Decoder.instance { h => + for { + _messageId <- h.get[Int]("message_id") + _messageThreadId <- h.get[Option[Int]]("message_thread_id") + _from <- h.get[Option[User]]("from") + _senderChat <- h.get[Option[Chat]]("sender_chat") + _date <- h.get[Int]("date") + _chat <- h.get[Chat]("chat") + _forwardOrigin <- h.get[Option[MessageOrigin]]("forward_origin") + _isTopicMessage <- h.get[Option[Boolean]]("is_topic_message") + _isAutomaticForward <- h.get[Option[Boolean]]("is_automatic_forward") + _replyToMessage <- h.get[Option[Message]]("reply_to_message") + _externalReply <- h.get[Option[ExternalReplyInfo]]("external_reply") + _quote <- h.get[Option[TextQuote]]("quote") + _viaBot <- h.get[Option[User]]("via_bot") + _editDate <- h.get[Option[Int]]("edit_date") + _hasProtectedContent <- h.get[Option[Boolean]]("has_protected_content") + _mediaGroupId <- h.get[Option[String]]("media_group_id") + _authorSignature <- h.get[Option[String]]("author_signature") + _text <- h.get[Option[String]]("text") + _entities <- h.getOrElse[List[MessageEntity]]("entities")(List.empty) + _linkPreviewOptions <- h.get[Option[LinkPreviewOptions]]("link_preview_options") + _animation <- h.get[Option[Animation]]("animation") + _audio <- h.get[Option[Audio]]("audio") + _document <- h.get[Option[Document]]("document") + _photo <- h.getOrElse[List[PhotoSize]]("photo")(List.empty) + _sticker <- h.get[Option[Sticker]]("sticker") + _story <- h.get[Option[Story.type]]("story") + _video <- h.get[Option[Video]]("video") + _videoNote <- h.get[Option[VideoNote]]("video_note") + _voice <- h.get[Option[Voice]]("voice") + _caption <- h.get[Option[String]]("caption") + _captionEntities <- h.getOrElse[List[MessageEntity]]("caption_entities")(List.empty) + _hasMediaSpoiler <- h.get[Option[Boolean]]("has_media_spoiler") + _contact <- h.get[Option[Contact]]("contact") + _dice <- h.get[Option[Dice]]("dice") + _game <- h.get[Option[Game]]("game") + _poll <- h.get[Option[Poll]]("poll") + _venue <- h.get[Option[Venue]]("venue") + _location <- h.get[Option[Location]]("location") + _newChatMembers <- h.getOrElse[List[User]]("new_chat_members")(List.empty) + _leftChatMember <- h.get[Option[User]]("left_chat_member") + _newChatTitle <- h.get[Option[String]]("new_chat_title") + _newChatPhoto <- h.getOrElse[List[PhotoSize]]("new_chat_photo")(List.empty) + _deleteChatPhoto <- h.get[Option[Boolean]]("delete_chat_photo") + _groupChatCreated <- h.get[Option[Boolean]]("group_chat_created") + _supergroupChatCreated <- h.get[Option[Boolean]]("supergroup_chat_created") + _channelChatCreated <- h.get[Option[Boolean]]("channel_chat_created") + _messageAutoDeleteTimerChanged <- h.get[Option[MessageAutoDeleteTimerChanged]]( + "message_auto_delete_timer_changed" + ) + _migrateToChatId <- h.get[Option[Long]]("migrate_to_chat_id") + _migrateFromChatId <- h.get[Option[Long]]("migrate_from_chat_id") + _pinnedMessage <- h.get[Option[MaybeInaccessibleMessage]]("pinned_message") + _invoice <- h.get[Option[Invoice]]("invoice") + _successfulPayment <- h.get[Option[SuccessfulPayment]]("successful_payment") + _usersShared <- h.get[Option[UsersShared]]("users_shared") + _chatShared <- h.get[Option[ChatShared]]("chat_shared") + _connectedWebsite <- h.get[Option[String]]("connected_website") + _writeAccessAllowed <- h.get[Option[WriteAccessAllowed]]("write_access_allowed") + _passportData <- h.get[Option[PassportData]]("passport_data") + _proximityAlertTriggered <- h.get[Option[ProximityAlertTriggered]]("proximity_alert_triggered") + _forumTopicCreated <- h.get[Option[ForumTopicCreated]]("forum_topic_created") + _forumTopicEdited <- h.get[Option[ForumTopicEdited]]("forum_topic_edited") + _forumTopicClosed <- h.get[Option[ForumTopicClosed.type]]("forum_topic_closed") + _forumTopicReopened <- h.get[Option[ForumTopicReopened.type]]("forum_topic_reopened") + _generalForumTopicHidden <- h.get[Option[GeneralForumTopicHidden.type]]("general_forum_topic_hidden") + _generalForumTopicUnhidden <- h.get[Option[GeneralForumTopicUnhidden.type]]("general_forum_topic_unhidden") + _giveawayCreated <- h.get[Option[GiveawayCreated.type]]("giveaway_created") + _giveaway <- h.get[Option[Giveaway]]("giveaway") + _giveawayWinners <- h.get[Option[GiveawayWinners]]("giveaway_winners") + _giveawayCompleted <- h.get[Option[GiveawayCompleted]]("giveaway_completed") + _videoChatScheduled <- h.get[Option[VideoChatScheduled]]("video_chat_scheduled") + _videoChatStarted <- h.get[Option[VideoChatStarted.type]]("video_chat_started") + _videoChatEnded <- h.get[Option[VideoChatEnded]]("video_chat_ended") + _videoChatParticipantsInvited <- h.get[Option[VideoChatParticipantsInvited]]("video_chat_participants_invited") + _webAppData <- h.get[Option[WebAppData]]("web_app_data") + _replyMarkup <- h.get[Option[InlineKeyboardMarkup]]("reply_markup") + } yield { + Message( + messageId = _messageId, + messageThreadId = _messageThreadId, + from = _from, + senderChat = _senderChat, + date = _date, + chat = _chat, + forwardOrigin = _forwardOrigin, + isTopicMessage = _isTopicMessage, + isAutomaticForward = _isAutomaticForward, + replyToMessage = _replyToMessage, + externalReply = _externalReply, + quote = _quote, + viaBot = _viaBot, + editDate = _editDate, + hasProtectedContent = _hasProtectedContent, + mediaGroupId = _mediaGroupId, + authorSignature = _authorSignature, + text = _text, + entities = _entities, + linkPreviewOptions = _linkPreviewOptions, + animation = _animation, + audio = _audio, + document = _document, + photo = _photo, + sticker = _sticker, + story = _story, + video = _video, + videoNote = _videoNote, + voice = _voice, + caption = _caption, + captionEntities = _captionEntities, + hasMediaSpoiler = _hasMediaSpoiler, + contact = _contact, + dice = _dice, + game = _game, + poll = _poll, + venue = _venue, + location = _location, + newChatMembers = _newChatMembers, + leftChatMember = _leftChatMember, + newChatTitle = _newChatTitle, + newChatPhoto = _newChatPhoto, + deleteChatPhoto = _deleteChatPhoto, + groupChatCreated = _groupChatCreated, + supergroupChatCreated = _supergroupChatCreated, + channelChatCreated = _channelChatCreated, + messageAutoDeleteTimerChanged = _messageAutoDeleteTimerChanged, + migrateToChatId = _migrateToChatId, + migrateFromChatId = _migrateFromChatId, + pinnedMessage = _pinnedMessage, + invoice = _invoice, + successfulPayment = _successfulPayment, + usersShared = _usersShared, + chatShared = _chatShared, + connectedWebsite = _connectedWebsite, + writeAccessAllowed = _writeAccessAllowed, + passportData = _passportData, + proximityAlertTriggered = _proximityAlertTriggered, + forumTopicCreated = _forumTopicCreated, + forumTopicEdited = _forumTopicEdited, + forumTopicClosed = _forumTopicClosed, + forumTopicReopened = _forumTopicReopened, + generalForumTopicHidden = _generalForumTopicHidden, + generalForumTopicUnhidden = _generalForumTopicUnhidden, + giveawayCreated = _giveawayCreated, + giveaway = _giveaway, + giveawayWinners = _giveawayWinners, + giveawayCompleted = _giveawayCompleted, + videoChatScheduled = _videoChatScheduled, + videoChatStarted = _videoChatStarted, + videoChatEnded = _videoChatEnded, + videoChatParticipantsInvited = _videoChatParticipantsInvited, + webAppData = _webAppData, + replyMarkup = _replyMarkup + ) + } + } + + implicit lazy val inaccessiblemessageEncoder: Encoder[InaccessibleMessage] = + (x: InaccessibleMessage) => { + Json.fromFields( + List( + "chat" -> x.chat.asJson, + "message_id" -> x.messageId.asJson, + "date" -> x.date.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val inaccessiblemessageDecoder: Decoder[InaccessibleMessage] = + Decoder.instance { h => + for { + _chat <- h.get[Chat]("chat") + _messageId <- h.get[Int]("message_id") + _date <- h.get[Int]("date") + } yield { + InaccessibleMessage(chat = _chat, messageId = _messageId, date = _date) + } + } + + implicit lazy val messageoriginEncoder: Encoder[MessageOrigin] = { + case x: MessageOriginUser => x.asJson + case x: MessageOriginChannel => x.asJson + case x: MessageOriginHiddenUser => x.asJson + case x: MessageOriginChat => x.asJson + } + + implicit lazy val messageoriginDecoder: Decoder[MessageOrigin] = { + List[Decoder[MessageOrigin]]( + messageoriginuserDecoder.widen, + messageoriginchannelDecoder.widen, + messageoriginhiddenuserDecoder.widen, + messageoriginchatDecoder.widen + ).reduceLeft(_ or _) + } + + implicit lazy val messageoriginuserEncoder: Encoder[MessageOriginUser] = + (x: MessageOriginUser) => { + Json.fromFields( + List( + "type" -> x.`type`.asJson, + "date" -> x.date.asJson, + "sender_user" -> x.senderUser.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val messageoriginuserDecoder: Decoder[MessageOriginUser] = + Decoder.instance { h => + for { + _type <- h.get[String]("type") + _date <- h.get[Int]("date") + _senderUser <- h.get[User]("sender_user") + } yield { + MessageOriginUser(`type` = _type, date = _date, senderUser = _senderUser) + } + } + + implicit lazy val messageoriginchannelEncoder: Encoder[MessageOriginChannel] = + (x: MessageOriginChannel) => { + Json.fromFields( + List( + "type" -> x.`type`.asJson, + "date" -> x.date.asJson, + "chat" -> x.chat.asJson, + "message_id" -> x.messageId.asJson, + "author_signature" -> x.authorSignature.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val messageoriginchannelDecoder: Decoder[MessageOriginChannel] = + Decoder.instance { h => + for { + _type <- h.get[String]("type") + _date <- h.get[Int]("date") + _chat <- h.get[Chat]("chat") + _messageId <- h.get[Int]("message_id") + _authorSignature <- h.get[Option[String]]("author_signature") + } yield { + MessageOriginChannel( + `type` = _type, + date = _date, + chat = _chat, + messageId = _messageId, + authorSignature = _authorSignature + ) + } + } + + implicit lazy val messageoriginhiddenuserEncoder: Encoder[MessageOriginHiddenUser] = + (x: MessageOriginHiddenUser) => { + Json.fromFields( + List( + "type" -> x.`type`.asJson, + "date" -> x.date.asJson, + "sender_user_name" -> x.senderUserName.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val messageoriginhiddenuserDecoder: Decoder[MessageOriginHiddenUser] = + Decoder.instance { h => + for { + _type <- h.get[String]("type") + _date <- h.get[Int]("date") + _senderUserName <- h.get[String]("sender_user_name") + } yield { + MessageOriginHiddenUser(`type` = _type, date = _date, senderUserName = _senderUserName) + } + } + + implicit lazy val messageoriginchatEncoder: Encoder[MessageOriginChat] = + (x: MessageOriginChat) => { + Json.fromFields( + List( + "type" -> x.`type`.asJson, + "date" -> x.date.asJson, + "sender_chat" -> x.senderChat.asJson, + "author_signature" -> x.authorSignature.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val messageoriginchatDecoder: Decoder[MessageOriginChat] = + Decoder.instance { h => + for { + _type <- h.get[String]("type") + _date <- h.get[Int]("date") + _senderChat <- h.get[Chat]("sender_chat") + _authorSignature <- h.get[Option[String]]("author_signature") + } yield { + MessageOriginChat(`type` = _type, date = _date, senderChat = _senderChat, authorSignature = _authorSignature) + } + } + implicit lazy val chatmemberEncoder: Encoder[ChatMember] = { case x: ChatMemberOwner => x.asJson case x: ChatMemberAdministrator => x.asJson @@ -461,6 +852,58 @@ object CirceImplicits { } } + implicit lazy val reactiontypeEncoder: Encoder[ReactionType] = { + case x: ReactionTypeEmoji => x.asJson + case x: ReactionTypeCustomEmoji => x.asJson + } + + implicit lazy val reactiontypeDecoder: Decoder[ReactionType] = { + List[Decoder[ReactionType]]( + reactiontypeemojiDecoder.widen, + reactiontypecustomemojiDecoder.widen + ).reduceLeft(_ or _) + } + + implicit lazy val reactiontypeemojiEncoder: Encoder[ReactionTypeEmoji] = + (x: ReactionTypeEmoji) => { + Json.fromFields( + List( + "type" -> x.`type`.asJson, + "emoji" -> x.emoji.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val reactiontypeemojiDecoder: Decoder[ReactionTypeEmoji] = + Decoder.instance { h => + for { + _type <- h.get[String]("type") + _emoji <- h.get[String]("emoji") + } yield { + ReactionTypeEmoji(`type` = _type, emoji = _emoji) + } + } + + implicit lazy val reactiontypecustomemojiEncoder: Encoder[ReactionTypeCustomEmoji] = + (x: ReactionTypeCustomEmoji) => { + Json.fromFields( + List( + "type" -> x.`type`.asJson, + "custom_emoji_id" -> x.customEmojiId.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val reactiontypecustomemojiDecoder: Decoder[ReactionTypeCustomEmoji] = + Decoder.instance { h => + for { + _type <- h.get[String]("type") + _customEmojiId <- h.get[String]("custom_emoji_id") + } yield { + ReactionTypeCustomEmoji(`type` = _type, customEmojiId = _customEmojiId) + } + } + implicit lazy val botcommandscopeEncoder: Encoder[BotCommandScope] = { case all_chat_administrators: BotCommandScopeAllChatAdministrators.type => all_chat_administrators.asJson.mapObject(_.add("type", Json.fromString("all_chat_administrators"))) @@ -615,6 +1058,89 @@ object CirceImplicits { implicit lazy val menubuttoncommandsDecoder: Decoder[MenuButtonCommands.type] = (_: HCursor) => Right(MenuButtonCommands) + implicit lazy val chatboostsourceEncoder: Encoder[ChatBoostSource] = { + case x: ChatBoostSourceGiftCode => x.asJson + case x: ChatBoostSourceGiveaway => x.asJson + case x: ChatBoostSourcePremium => x.asJson + } + + implicit lazy val chatboostsourceDecoder: Decoder[ChatBoostSource] = { + List[Decoder[ChatBoostSource]]( + chatboostsourcegiftcodeDecoder.widen, + chatboostsourcegiveawayDecoder.widen, + chatboostsourcepremiumDecoder.widen + ).reduceLeft(_ or _) + } + + implicit lazy val chatboostsourcegiftcodeEncoder: Encoder[ChatBoostSourceGiftCode] = + (x: ChatBoostSourceGiftCode) => { + Json.fromFields( + List( + "source" -> x.source.asJson, + "user" -> x.user.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val chatboostsourcegiftcodeDecoder: Decoder[ChatBoostSourceGiftCode] = + Decoder.instance { h => + for { + _source <- h.get[String]("source") + _user <- h.get[User]("user") + } yield { + ChatBoostSourceGiftCode(source = _source, user = _user) + } + } + + implicit lazy val chatboostsourcegiveawayEncoder: Encoder[ChatBoostSourceGiveaway] = + (x: ChatBoostSourceGiveaway) => { + Json.fromFields( + List( + "source" -> x.source.asJson, + "giveaway_message_id" -> x.giveawayMessageId.asJson, + "user" -> x.user.asJson, + "is_unclaimed" -> x.isUnclaimed.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val chatboostsourcegiveawayDecoder: Decoder[ChatBoostSourceGiveaway] = + Decoder.instance { h => + for { + _source <- h.get[String]("source") + _giveawayMessageId <- h.get[Int]("giveaway_message_id") + _user <- h.get[Option[User]]("user") + _isUnclaimed <- h.get[Option[Boolean]]("is_unclaimed") + } yield { + ChatBoostSourceGiveaway( + source = _source, + giveawayMessageId = _giveawayMessageId, + user = _user, + isUnclaimed = _isUnclaimed + ) + } + } + + implicit lazy val chatboostsourcepremiumEncoder: Encoder[ChatBoostSourcePremium] = + (x: ChatBoostSourcePremium) => { + Json.fromFields( + List( + "source" -> x.source.asJson, + "user" -> x.user.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val chatboostsourcepremiumDecoder: Decoder[ChatBoostSourcePremium] = + Decoder.instance { h => + for { + _source <- h.get[String]("source") + _user <- h.get[User]("user") + } yield { + ChatBoostSourcePremium(source = _source, user = _user) + } + } + implicit lazy val inputmediaEncoder: Encoder[InputMedia] = { case photo: InputMediaPhoto => photo.asJson.mapObject(_.add("type", Json.fromString("photo"))) case document: InputMediaDocument => document.asJson.mapObject(_.add("type", Json.fromString("document"))) @@ -2033,10 +2559,10 @@ object CirceImplicits { (x: InputTextMessageContent) => { Json.fromFields( List( - "message_text" -> x.messageText.asJson, - "parse_mode" -> x.parseMode.asJson, - "entities" -> x.entities.asJson, - "disable_web_page_preview" -> x.disableWebPagePreview.asJson + "message_text" -> x.messageText.asJson, + "parse_mode" -> x.parseMode.asJson, + "entities" -> x.entities.asJson, + "link_preview_options" -> x.linkPreviewOptions.asJson ).filter(!_._2.isNull) ) } @@ -2044,16 +2570,16 @@ object CirceImplicits { implicit lazy val inputtextmessagecontentDecoder: Decoder[InputTextMessageContent] = Decoder.instance { h => for { - _messageText <- h.get[String]("message_text") - _parseMode <- h.get[Option[ParseMode]]("parse_mode") - _entities <- h.getOrElse[List[MessageEntity]]("entities")(List.empty) - _disableWebPagePreview <- h.get[Option[Boolean]]("disable_web_page_preview") + _messageText <- h.get[String]("message_text") + _parseMode <- h.get[Option[ParseMode]]("parse_mode") + _entities <- h.getOrElse[List[MessageEntity]]("entities")(List.empty) + _linkPreviewOptions <- h.get[Option[LinkPreviewOptions]]("link_preview_options") } yield { InputTextMessageContent( messageText = _messageText, parseMode = _parseMode, entities = _entities, - disableWebPagePreview = _disableWebPagePreview + linkPreviewOptions = _linkPreviewOptions ) } } @@ -2311,7 +2837,9 @@ object CirceImplicits { case spoiler: SpoilerMessageEntity => spoiler.asJson.mapObject(_.add("type", Json.fromString("spoiler"))) case mention: MentionMessageEntity => mention.asJson.mapObject(_.add("type", Json.fromString("mention"))) case hashtag: HashtagMessageEntity => hashtag.asJson.mapObject(_.add("type", Json.fromString("hashtag"))) - case text_link: TextLinkMessageEntity => text_link.asJson.mapObject(_.add("type", Json.fromString("text_link"))) + case blockquote: BlockquoteMessageEntity => + blockquote.asJson.mapObject(_.add("type", Json.fromString("blockquote"))) + case text_link: TextLinkMessageEntity => text_link.asJson.mapObject(_.add("type", Json.fromString("text_link"))) case strikethrough: StrikethroughMessageEntity => strikethrough.asJson.mapObject(_.add("type", Json.fromString("strikethrough"))) } @@ -2334,6 +2862,7 @@ object CirceImplicits { case "spoiler" => Decoder[SpoilerMessageEntity] case "mention" => Decoder[MentionMessageEntity] case "hashtag" => Decoder[HashtagMessageEntity] + case "blockquote" => Decoder[BlockquoteMessageEntity] case "text_link" => Decoder[TextLinkMessageEntity] case "strikethrough" => Decoder[StrikethroughMessageEntity] case unknown => throw DecodingError(s"Unknown type for MessageEntity: $unknown") @@ -2482,6 +3011,26 @@ object CirceImplicits { } } + implicit lazy val blockquotemessageentityEncoder: Encoder[BlockquoteMessageEntity] = + (x: BlockquoteMessageEntity) => { + Json.fromFields( + List( + "offset" -> x.offset.asJson, + "length" -> x.length.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val blockquotemessageentityDecoder: Decoder[BlockquoteMessageEntity] = + Decoder.instance { h => + for { + _offset <- h.get[Int]("offset") + _length <- h.get[Int]("length") + } yield { + BlockquoteMessageEntity(offset = _offset, length = _length) + } + } + implicit lazy val boldmessageentityEncoder: Encoder[BoldMessageEntity] = (x: BoldMessageEntity) => { Json.fromFields( @@ -2732,6 +3281,26 @@ object CirceImplicits { } } + implicit lazy val chatboostupdatedEncoder: Encoder[ChatBoostUpdated] = + (x: ChatBoostUpdated) => { + Json.fromFields( + List( + "chat" -> x.chat.asJson, + "boost" -> x.boost.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val chatboostupdatedDecoder: Decoder[ChatBoostUpdated] = + Decoder.instance { h => + for { + _chat <- h.get[Chat]("chat") + _boost <- h.get[ChatBoost]("boost") + } yield { + ChatBoostUpdated(chat = _chat, boost = _boost) + } + } + implicit lazy val animationEncoder: Encoder[Animation] = (x: Animation) => { Json.fromFields( @@ -2824,6 +3393,11 @@ object CirceImplicits { "is_forum" -> x.isForum.asJson, "photo" -> x.photo.asJson, "active_usernames" -> x.activeUsernames.asJson, + "available_reactions" -> x.availableReactions.asJson, + "accent_color_id" -> x.accentColorId.asJson, + "background_custom_emoji_id" -> x.backgroundCustomEmojiId.asJson, + "profile_accent_color_id" -> x.profileAccentColorId.asJson, + "profile_background_custom_emoji_id" -> x.profileBackgroundCustomEmojiId.asJson, "emoji_status_custom_emoji_id" -> x.emojiStatusCustomEmojiId.asJson, "emoji_status_expiration_date" -> x.emojiStatusExpirationDate.asJson, "bio" -> x.bio.asJson, @@ -2840,6 +3414,7 @@ object CirceImplicits { "has_aggressive_anti_spam_enabled" -> x.hasAggressiveAntiSpamEnabled.asJson, "has_hidden_members" -> x.hasHiddenMembers.asJson, "has_protected_content" -> x.hasProtectedContent.asJson, + "has_visible_history" -> x.hasVisibleHistory.asJson, "sticker_set_name" -> x.stickerSetName.asJson, "can_set_sticker_set" -> x.canSetStickerSet.asJson, "linked_chat_id" -> x.linkedChatId.asJson, @@ -2860,6 +3435,11 @@ object CirceImplicits { _isForum <- h.get[Option[Boolean]]("is_forum") _photo <- h.get[Option[ChatPhoto]]("photo") _activeUsernames <- h.getOrElse[List[String]]("active_usernames")(List.empty) + _availableReactions <- h.getOrElse[List[ReactionType]]("available_reactions")(List.empty) + _accentColorId <- h.get[Option[Int]]("accent_color_id") + _backgroundCustomEmojiId <- h.get[Option[String]]("background_custom_emoji_id") + _profileAccentColorId <- h.get[Option[Int]]("profile_accent_color_id") + _profileBackgroundCustomEmojiId <- h.get[Option[String]]("profile_background_custom_emoji_id") _emojiStatusCustomEmojiId <- h.get[Option[String]]("emoji_status_custom_emoji_id") _emojiStatusExpirationDate <- h.get[Option[Int]]("emoji_status_expiration_date") _bio <- h.get[Option[String]]("bio") @@ -2876,6 +3456,7 @@ object CirceImplicits { _hasAggressiveAntiSpamEnabled <- h.get[Option[Boolean]]("has_aggressive_anti_spam_enabled") _hasHiddenMembers <- h.get[Option[Boolean]]("has_hidden_members") _hasProtectedContent <- h.get[Option[Boolean]]("has_protected_content") + _hasVisibleHistory <- h.get[Option[Boolean]]("has_visible_history") _stickerSetName <- h.get[Option[String]]("sticker_set_name") _canSetStickerSet <- h.get[Option[Boolean]]("can_set_sticker_set") _linkedChatId <- h.get[Option[Long]]("linked_chat_id") @@ -2891,6 +3472,11 @@ object CirceImplicits { isForum = _isForum, photo = _photo, activeUsernames = _activeUsernames, + availableReactions = _availableReactions, + accentColorId = _accentColorId, + backgroundCustomEmojiId = _backgroundCustomEmojiId, + profileAccentColorId = _profileAccentColorId, + profileBackgroundCustomEmojiId = _profileBackgroundCustomEmojiId, emojiStatusCustomEmojiId = _emojiStatusCustomEmojiId, emojiStatusExpirationDate = _emojiStatusExpirationDate, bio = _bio, @@ -2907,6 +3493,7 @@ object CirceImplicits { hasAggressiveAntiSpamEnabled = _hasAggressiveAntiSpamEnabled, hasHiddenMembers = _hasHiddenMembers, hasProtectedContent = _hasProtectedContent, + hasVisibleHistory = _hasVisibleHistory, stickerSetName = _stickerSetName, canSetStickerSet = _canSetStickerSet, linkedChatId = _linkedChatId, @@ -3088,25 +3675,8 @@ object CirceImplicits { } } - implicit lazy val usersharedEncoder: Encoder[UserShared] = - (x: UserShared) => { - Json.fromFields( - List( - "request_id" -> x.requestId.asJson, - "user_id" -> x.userId.asJson - ).filter(!_._2.isNull) - ) - } - - implicit lazy val usersharedDecoder: Decoder[UserShared] = - Decoder.instance { h => - for { - _requestId <- h.get[Int]("request_id") - _userId <- h.get[Long]("user_id") - } yield { - UserShared(requestId = _requestId, userId = _userId) - } - } + implicit lazy val giveawaycreatedEncoder: Encoder[GiveawayCreated.type] = (_: GiveawayCreated.type) => ().asJson + implicit lazy val giveawaycreatedDecoder: Decoder[GiveawayCreated.type] = (_: HCursor) => Right(GiveawayCreated) implicit lazy val botshortdescriptionEncoder: Encoder[BotShortDescription] = (x: BotShortDescription) => { @@ -3231,28 +3801,82 @@ object CirceImplicits { } } - implicit lazy val inputfileEncoder: Encoder[InputFile.type] = (_: InputFile.type) => ().asJson - implicit lazy val inputfileDecoder: Decoder[InputFile.type] = (_: HCursor) => Right(InputFile) - + implicit lazy val inputfileEncoder: Encoder[InputFile.type] = (_: InputFile.type) => ().asJson + implicit lazy val inputfileDecoder: Decoder[InputFile.type] = (_: HCursor) => Right(InputFile) + + implicit lazy val giveawaywinnersEncoder: Encoder[GiveawayWinners] = + (x: GiveawayWinners) => { + Json.fromFields( + List( + "chat" -> x.chat.asJson, + "giveaway_message_id" -> x.giveawayMessageId.asJson, + "winners_selection_date" -> x.winnersSelectionDate.asJson, + "winner_count" -> x.winnerCount.asJson, + "winners" -> x.winners.asJson, + "additional_chat_count" -> x.additionalChatCount.asJson, + "premium_subscription_month_count" -> x.premiumSubscriptionMonthCount.asJson, + "unclaimed_prize_count" -> x.unclaimedPrizeCount.asJson, + "only_new_members" -> x.onlyNewMembers.asJson, + "was_refunded" -> x.wasRefunded.asJson, + "prize_description" -> x.prizeDescription.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val giveawaywinnersDecoder: Decoder[GiveawayWinners] = + Decoder.instance { h => + for { + _chat <- h.get[Chat]("chat") + _giveawayMessageId <- h.get[Int]("giveaway_message_id") + _winnersSelectionDate <- h.get[Int]("winners_selection_date") + _winnerCount <- h.get[Int]("winner_count") + _winners <- h.getOrElse[List[User]]("winners")(List.empty) + _additionalChatCount <- h.get[Option[Int]]("additional_chat_count") + _premiumSubscriptionMonthCount <- h.get[Option[Int]]("premium_subscription_month_count") + _unclaimedPrizeCount <- h.get[Option[Int]]("unclaimed_prize_count") + _onlyNewMembers <- h.get[Option[Boolean]]("only_new_members") + _wasRefunded <- h.get[Option[Boolean]]("was_refunded") + _prizeDescription <- h.get[Option[String]]("prize_description") + } yield { + GiveawayWinners( + chat = _chat, + giveawayMessageId = _giveawayMessageId, + winnersSelectionDate = _winnersSelectionDate, + winnerCount = _winnerCount, + winners = _winners, + additionalChatCount = _additionalChatCount, + premiumSubscriptionMonthCount = _premiumSubscriptionMonthCount, + unclaimedPrizeCount = _unclaimedPrizeCount, + onlyNewMembers = _onlyNewMembers, + wasRefunded = _wasRefunded, + prizeDescription = _prizeDescription + ) + } + } + implicit lazy val updateEncoder: Encoder[Update] = (x: Update) => { Json.fromFields( List( - "update_id" -> x.updateId.asJson, - "message" -> x.message.asJson, - "edited_message" -> x.editedMessage.asJson, - "channel_post" -> x.channelPost.asJson, - "edited_channel_post" -> x.editedChannelPost.asJson, - "inline_query" -> x.inlineQuery.asJson, - "chosen_inline_result" -> x.chosenInlineResult.asJson, - "callback_query" -> x.callbackQuery.asJson, - "shipping_query" -> x.shippingQuery.asJson, - "pre_checkout_query" -> x.preCheckoutQuery.asJson, - "poll" -> x.poll.asJson, - "poll_answer" -> x.pollAnswer.asJson, - "my_chat_member" -> x.myChatMember.asJson, - "chat_member" -> x.chatMember.asJson, - "chat_join_request" -> x.chatJoinRequest.asJson + "update_id" -> x.updateId.asJson, + "message" -> x.message.asJson, + "edited_message" -> x.editedMessage.asJson, + "channel_post" -> x.channelPost.asJson, + "edited_channel_post" -> x.editedChannelPost.asJson, + "message_reaction" -> x.messageReaction.asJson, + "message_reaction_count" -> x.messageReactionCount.asJson, + "inline_query" -> x.inlineQuery.asJson, + "chosen_inline_result" -> x.chosenInlineResult.asJson, + "callback_query" -> x.callbackQuery.asJson, + "shipping_query" -> x.shippingQuery.asJson, + "pre_checkout_query" -> x.preCheckoutQuery.asJson, + "poll" -> x.poll.asJson, + "poll_answer" -> x.pollAnswer.asJson, + "my_chat_member" -> x.myChatMember.asJson, + "chat_member" -> x.chatMember.asJson, + "chat_join_request" -> x.chatJoinRequest.asJson, + "chat_boost" -> x.chatBoost.asJson, + "removed_chat_boost" -> x.removedChatBoost.asJson ).filter(!_._2.isNull) ) } @@ -3260,21 +3884,25 @@ object CirceImplicits { implicit lazy val updateDecoder: Decoder[Update] = Decoder.instance { h => for { - _updateId <- h.get[Int]("update_id") - _message <- h.get[Option[Message]]("message") - _editedMessage <- h.get[Option[Message]]("edited_message") - _channelPost <- h.get[Option[Message]]("channel_post") - _editedChannelPost <- h.get[Option[Message]]("edited_channel_post") - _inlineQuery <- h.get[Option[InlineQuery]]("inline_query") - _chosenInlineResult <- h.get[Option[ChosenInlineResult]]("chosen_inline_result") - _callbackQuery <- h.get[Option[CallbackQuery]]("callback_query") - _shippingQuery <- h.get[Option[ShippingQuery]]("shipping_query") - _preCheckoutQuery <- h.get[Option[PreCheckoutQuery]]("pre_checkout_query") - _poll <- h.get[Option[Poll]]("poll") - _pollAnswer <- h.get[Option[PollAnswer]]("poll_answer") - _myChatMember <- h.get[Option[ChatMemberUpdated]]("my_chat_member") - _chatMember <- h.get[Option[ChatMemberUpdated]]("chat_member") - _chatJoinRequest <- h.get[Option[ChatJoinRequest]]("chat_join_request") + _updateId <- h.get[Int]("update_id") + _message <- h.get[Option[Message]]("message") + _editedMessage <- h.get[Option[Message]]("edited_message") + _channelPost <- h.get[Option[Message]]("channel_post") + _editedChannelPost <- h.get[Option[Message]]("edited_channel_post") + _messageReaction <- h.get[Option[MessageReactionUpdated]]("message_reaction") + _messageReactionCount <- h.get[Option[MessageReactionCountUpdated]]("message_reaction_count") + _inlineQuery <- h.get[Option[InlineQuery]]("inline_query") + _chosenInlineResult <- h.get[Option[ChosenInlineResult]]("chosen_inline_result") + _callbackQuery <- h.get[Option[CallbackQuery]]("callback_query") + _shippingQuery <- h.get[Option[ShippingQuery]]("shipping_query") + _preCheckoutQuery <- h.get[Option[PreCheckoutQuery]]("pre_checkout_query") + _poll <- h.get[Option[Poll]]("poll") + _pollAnswer <- h.get[Option[PollAnswer]]("poll_answer") + _myChatMember <- h.get[Option[ChatMemberUpdated]]("my_chat_member") + _chatMember <- h.get[Option[ChatMemberUpdated]]("chat_member") + _chatJoinRequest <- h.get[Option[ChatJoinRequest]]("chat_join_request") + _chatBoost <- h.get[Option[ChatBoostUpdated]]("chat_boost") + _removedChatBoost <- h.get[Option[ChatBoostRemoved]]("removed_chat_boost") } yield { Update( updateId = _updateId, @@ -3282,6 +3910,8 @@ object CirceImplicits { editedMessage = _editedMessage, channelPost = _channelPost, editedChannelPost = _editedChannelPost, + messageReaction = _messageReaction, + messageReactionCount = _messageReactionCount, inlineQuery = _inlineQuery, chosenInlineResult = _chosenInlineResult, callbackQuery = _callbackQuery, @@ -3291,7 +3921,9 @@ object CirceImplicits { pollAnswer = _pollAnswer, myChatMember = _myChatMember, chatMember = _chatMember, - chatJoinRequest = _chatJoinRequest + chatJoinRequest = _chatJoinRequest, + chatBoost = _chatBoost, + removedChatBoost = _removedChatBoost ) } } @@ -3328,7 +3960,7 @@ object CirceImplicits { Json.fromFields( List( "text" -> x.text.asJson, - "request_user" -> x.requestUser.asJson, + "request_users" -> x.requestUsers.asJson, "request_chat" -> x.requestChat.asJson, "request_contact" -> x.requestContact.asJson, "request_location" -> x.requestLocation.asJson, @@ -3342,7 +3974,7 @@ object CirceImplicits { Decoder.instance { h => for { _text <- h.get[String]("text") - _requestUser <- h.get[Option[KeyboardButtonRequestUser]]("request_user") + _requestUsers <- h.get[Option[KeyboardButtonRequestUsers]]("request_users") _requestChat <- h.get[Option[KeyboardButtonRequestChat]]("request_chat") _requestContact <- h.get[Option[Boolean]]("request_contact") _requestLocation <- h.get[Option[Boolean]]("request_location") @@ -3351,7 +3983,7 @@ object CirceImplicits { } yield { KeyboardButton( text = _text, - requestUser = _requestUser, + requestUsers = _requestUsers, requestChat = _requestChat, requestContact = _requestContact, requestLocation = _requestLocation, @@ -3459,6 +4091,26 @@ object CirceImplicits { implicit lazy val generalforumtopichiddenDecoder: Decoder[GeneralForumTopicHidden.type] = (_: HCursor) => Right(GeneralForumTopicHidden) + implicit lazy val userssharedEncoder: Encoder[UsersShared] = + (x: UsersShared) => { + Json.fromFields( + List( + "request_id" -> x.requestId.asJson, + "user_ids" -> x.userIds.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val userssharedDecoder: Decoder[UsersShared] = + Decoder.instance { h => + for { + _requestId <- h.get[Int]("request_id") + _userIds <- h.getOrElse[List[Long]]("user_ids")(List.empty) + } yield { + UsersShared(requestId = _requestId, userIds = _userIds) + } + } + implicit lazy val pollEncoder: Encoder[Poll] = (x: Poll) => { Json.fromFields( @@ -3553,6 +4205,92 @@ object CirceImplicits { } } + implicit lazy val externalreplyinfoEncoder: Encoder[ExternalReplyInfo] = + (x: ExternalReplyInfo) => { + Json.fromFields( + List( + "origin" -> x.origin.asJson, + "chat" -> x.chat.asJson, + "message_id" -> x.messageId.asJson, + "link_preview_options" -> x.linkPreviewOptions.asJson, + "animation" -> x.animation.asJson, + "audio" -> x.audio.asJson, + "document" -> x.document.asJson, + "photo" -> x.photo.asJson, + "sticker" -> x.sticker.asJson, + "story" -> x.story.asJson, + "video" -> x.video.asJson, + "video_note" -> x.videoNote.asJson, + "voice" -> x.voice.asJson, + "has_media_spoiler" -> x.hasMediaSpoiler.asJson, + "contact" -> x.contact.asJson, + "dice" -> x.dice.asJson, + "game" -> x.game.asJson, + "giveaway" -> x.giveaway.asJson, + "giveaway_winners" -> x.giveawayWinners.asJson, + "invoice" -> x.invoice.asJson, + "location" -> x.location.asJson, + "poll" -> x.poll.asJson, + "venue" -> x.venue.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val externalreplyinfoDecoder: Decoder[ExternalReplyInfo] = + Decoder.instance { h => + for { + _origin <- h.get[MessageOrigin]("origin") + _chat <- h.get[Option[Chat]]("chat") + _messageId <- h.get[Option[Int]]("message_id") + _linkPreviewOptions <- h.get[Option[LinkPreviewOptions]]("link_preview_options") + _animation <- h.get[Option[Animation]]("animation") + _audio <- h.get[Option[Audio]]("audio") + _document <- h.get[Option[Document]]("document") + _photo <- h.getOrElse[List[PhotoSize]]("photo")(List.empty) + _sticker <- h.get[Option[Sticker]]("sticker") + _story <- h.get[Option[Story.type]]("story") + _video <- h.get[Option[Video]]("video") + _videoNote <- h.get[Option[VideoNote]]("video_note") + _voice <- h.get[Option[Voice]]("voice") + _hasMediaSpoiler <- h.get[Option[Boolean]]("has_media_spoiler") + _contact <- h.get[Option[Contact]]("contact") + _dice <- h.get[Option[Dice]]("dice") + _game <- h.get[Option[Game]]("game") + _giveaway <- h.get[Option[Giveaway]]("giveaway") + _giveawayWinners <- h.get[Option[GiveawayWinners]]("giveaway_winners") + _invoice <- h.get[Option[Invoice]]("invoice") + _location <- h.get[Option[Location]]("location") + _poll <- h.get[Option[Poll]]("poll") + _venue <- h.get[Option[Venue]]("venue") + } yield { + ExternalReplyInfo( + origin = _origin, + chat = _chat, + messageId = _messageId, + linkPreviewOptions = _linkPreviewOptions, + animation = _animation, + audio = _audio, + document = _document, + photo = _photo, + sticker = _sticker, + story = _story, + video = _video, + videoNote = _videoNote, + voice = _voice, + hasMediaSpoiler = _hasMediaSpoiler, + contact = _contact, + dice = _dice, + game = _game, + giveaway = _giveaway, + giveawayWinners = _giveawayWinners, + invoice = _invoice, + location = _location, + poll = _poll, + venue = _venue + ) + } + } + implicit lazy val pollanswerEncoder: Encoder[PollAnswer] = (x: PollAnswer) => { Json.fromFields( @@ -3577,6 +4315,44 @@ object CirceImplicits { } } + implicit lazy val replyparametersEncoder: Encoder[ReplyParameters] = + (x: ReplyParameters) => { + Json.fromFields( + List( + "message_id" -> x.messageId.asJson, + "chat_id" -> x.chatId.asJson, + "allow_sending_without_reply" -> x.allowSendingWithoutReply.asJson, + "quote" -> x.quote.asJson, + "quote_parse_mode" -> x.quoteParseMode.asJson, + "quote_entities" -> x.quoteEntities.asJson, + "quote_position" -> x.quotePosition.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val replyparametersDecoder: Decoder[ReplyParameters] = + Decoder.instance { h => + for { + _messageId <- h.get[Int]("message_id") + _chatId <- h.get[Option[ChatId]]("chat_id") + _allowSendingWithoutReply <- h.get[Option[Boolean]]("allow_sending_without_reply") + _quote <- h.get[Option[String]]("quote") + _quoteParseMode <- h.get[Option[ParseMode]]("quote_parse_mode") + _quoteEntities <- h.getOrElse[List[MessageEntity]]("quote_entities")(List.empty) + _quotePosition <- h.get[Option[Int]]("quote_position") + } yield { + ReplyParameters( + messageId = _messageId, + chatId = _chatId, + allowSendingWithoutReply = _allowSendingWithoutReply, + quote = _quote, + quoteParseMode = _quoteParseMode, + quoteEntities = _quoteEntities, + quotePosition = _quotePosition + ) + } + } + implicit lazy val contactEncoder: Encoder[Contact] = (x: Contact) => { Json.fromFields( @@ -3649,6 +4425,30 @@ object CirceImplicits { } } + implicit lazy val chatboostremovedEncoder: Encoder[ChatBoostRemoved] = + (x: ChatBoostRemoved) => { + Json.fromFields( + List( + "chat" -> x.chat.asJson, + "boost_id" -> x.boostId.asJson, + "remove_date" -> x.removeDate.asJson, + "source" -> x.source.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val chatboostremovedDecoder: Decoder[ChatBoostRemoved] = + Decoder.instance { h => + for { + _chat <- h.get[Chat]("chat") + _boostId <- h.get[String]("boost_id") + _removeDate <- h.get[Int]("remove_date") + _source <- h.get[ChatBoostSource]("source") + } yield { + ChatBoostRemoved(chat = _chat, boostId = _boostId, removeDate = _removeDate, source = _source) + } + } + implicit lazy val messageautodeletetimerchangedEncoder: Encoder[MessageAutoDeleteTimerChanged] = (x: MessageAutoDeleteTimerChanged) => { Json.fromFields( @@ -3699,6 +4499,30 @@ object CirceImplicits { } } + implicit lazy val chatboostEncoder: Encoder[ChatBoost] = + (x: ChatBoost) => { + Json.fromFields( + List( + "boost_id" -> x.boostId.asJson, + "add_date" -> x.addDate.asJson, + "expiration_date" -> x.expirationDate.asJson, + "source" -> x.source.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val chatboostDecoder: Decoder[ChatBoost] = + Decoder.instance { h => + for { + _boostId <- h.get[String]("boost_id") + _addDate <- h.get[Int]("add_date") + _expirationDate <- h.get[Int]("expiration_date") + _source <- h.get[ChatBoostSource]("source") + } yield { + ChatBoost(boostId = _boostId, addDate = _addDate, expirationDate = _expirationDate, source = _source) + } + } + implicit lazy val labeledpriceEncoder: Encoder[LabeledPrice] = (x: LabeledPrice) => { Json.fromFields( @@ -3920,6 +4744,35 @@ object CirceImplicits { implicit lazy val storyEncoder: Encoder[Story.type] = (_: Story.type) => ().asJson implicit lazy val storyDecoder: Decoder[Story.type] = (_: HCursor) => Right(Story) + implicit lazy val keyboardbuttonrequestusersEncoder: Encoder[KeyboardButtonRequestUsers] = + (x: KeyboardButtonRequestUsers) => { + Json.fromFields( + List( + "request_id" -> x.requestId.asJson, + "user_is_bot" -> x.userIsBot.asJson, + "user_is_premium" -> x.userIsPremium.asJson, + "max_quantity" -> x.maxQuantity.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val keyboardbuttonrequestusersDecoder: Decoder[KeyboardButtonRequestUsers] = + Decoder.instance { h => + for { + _requestId <- h.get[Int]("request_id") + _userIsBot <- h.get[Option[Boolean]]("user_is_bot") + _userIsPremium <- h.get[Option[Boolean]]("user_is_premium") + _maxQuantity <- h.get[Option[Int]]("max_quantity") + } yield { + KeyboardButtonRequestUsers( + requestId = _requestId, + userIsBot = _userIsBot, + userIsPremium = _userIsPremium, + maxQuantity = _maxQuantity + ) + } + } + implicit lazy val passportdataEncoder: Encoder[PassportData] = (x: PassportData) => { Json.fromFields( @@ -4241,6 +5094,64 @@ object CirceImplicits { } } + implicit lazy val giveawaycompletedEncoder: Encoder[GiveawayCompleted] = + (x: GiveawayCompleted) => { + Json.fromFields( + List( + "winner_count" -> x.winnerCount.asJson, + "unclaimed_prize_count" -> x.unclaimedPrizeCount.asJson, + "giveaway_message" -> x.giveawayMessage.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val giveawaycompletedDecoder: Decoder[GiveawayCompleted] = + Decoder.instance { h => + for { + _winnerCount <- h.get[Int]("winner_count") + _unclaimedPrizeCount <- h.get[Option[Int]]("unclaimed_prize_count") + _giveawayMessage <- h.get[Option[Message]]("giveaway_message") + } yield { + GiveawayCompleted( + winnerCount = _winnerCount, + unclaimedPrizeCount = _unclaimedPrizeCount, + giveawayMessage = _giveawayMessage + ) + } + } + + implicit lazy val linkpreviewoptionsEncoder: Encoder[LinkPreviewOptions] = + (x: LinkPreviewOptions) => { + Json.fromFields( + List( + "is_disabled" -> x.isDisabled.asJson, + "url" -> x.url.asJson, + "prefer_small_media" -> x.preferSmallMedia.asJson, + "prefer_large_media" -> x.preferLargeMedia.asJson, + "show_above_text" -> x.showAboveText.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val linkpreviewoptionsDecoder: Decoder[LinkPreviewOptions] = + Decoder.instance { h => + for { + _isDisabled <- h.get[Option[Boolean]]("is_disabled") + _url <- h.get[Option[String]]("url") + _preferSmallMedia <- h.get[Option[Boolean]]("prefer_small_media") + _preferLargeMedia <- h.get[Option[Boolean]]("prefer_large_media") + _showAboveText <- h.get[Option[Boolean]]("show_above_text") + } yield { + LinkPreviewOptions( + isDisabled = _isDisabled, + url = _url, + preferSmallMedia = _preferSmallMedia, + preferLargeMedia = _preferLargeMedia, + showAboveText = _showAboveText + ) + } + } + implicit lazy val forumtopicEncoder: Encoder[ForumTopic] = (x: ForumTopic) => { Json.fromFields( @@ -4320,6 +5231,47 @@ object CirceImplicits { } } + implicit lazy val giveawayEncoder: Encoder[Giveaway] = + (x: Giveaway) => { + Json.fromFields( + List( + "chats" -> x.chats.asJson, + "winners_selection_date" -> x.winnersSelectionDate.asJson, + "winner_count" -> x.winnerCount.asJson, + "only_new_members" -> x.onlyNewMembers.asJson, + "has_public_winners" -> x.hasPublicWinners.asJson, + "prize_description" -> x.prizeDescription.asJson, + "country_codes" -> x.countryCodes.asJson, + "premium_subscription_month_count" -> x.premiumSubscriptionMonthCount.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val giveawayDecoder: Decoder[Giveaway] = + Decoder.instance { h => + for { + _chats <- h.getOrElse[List[Chat]]("chats")(List.empty) + _winnersSelectionDate <- h.get[Int]("winners_selection_date") + _winnerCount <- h.get[Int]("winner_count") + _onlyNewMembers <- h.get[Option[Boolean]]("only_new_members") + _hasPublicWinners <- h.get[Option[Boolean]]("has_public_winners") + _prizeDescription <- h.get[Option[String]]("prize_description") + _countryCodes <- h.getOrElse[List[String]]("country_codes")(List.empty) + _premiumSubscriptionMonthCount <- h.get[Option[Int]]("premium_subscription_month_count") + } yield { + Giveaway( + chats = _chats, + winnersSelectionDate = _winnersSelectionDate, + winnerCount = _winnerCount, + onlyNewMembers = _onlyNewMembers, + hasPublicWinners = _hasPublicWinners, + prizeDescription = _prizeDescription, + countryCodes = _countryCodes, + premiumSubscriptionMonthCount = _premiumSubscriptionMonthCount + ) + } + } + implicit lazy val chatphotoEncoder: Encoder[ChatPhoto] = (x: ChatPhoto) => { Json.fromFields( @@ -4522,282 +5474,47 @@ object CirceImplicits { "premium_animation" -> x.premiumAnimation.asJson, "mask_position" -> x.maskPosition.asJson, "custom_emoji_id" -> x.customEmojiId.asJson, - "needs_repainting" -> x.needsRepainting.asJson, - "file_size" -> x.fileSize.asJson - ).filter(!_._2.isNull) - ) - } - - implicit lazy val stickerDecoder: Decoder[Sticker] = - Decoder.instance { h => - for { - _fileId <- h.get[String]("file_id") - _fileUniqueId <- h.get[String]("file_unique_id") - _type <- h.get[String]("type") - _width <- h.get[Int]("width") - _height <- h.get[Int]("height") - _isAnimated <- h.get[Boolean]("is_animated") - _isVideo <- h.get[Boolean]("is_video") - _thumbnail <- h.get[Option[PhotoSize]]("thumbnail") - _emoji <- h.get[Option[String]]("emoji") - _setName <- h.get[Option[String]]("set_name") - _premiumAnimation <- h.get[Option[File]]("premium_animation") - _maskPosition <- h.get[Option[MaskPosition]]("mask_position") - _customEmojiId <- h.get[Option[String]]("custom_emoji_id") - _needsRepainting <- h.get[Option[Boolean]]("needs_repainting") - _fileSize <- h.get[Option[Long]]("file_size") - } yield { - Sticker( - fileId = _fileId, - fileUniqueId = _fileUniqueId, - `type` = _type, - width = _width, - height = _height, - isAnimated = _isAnimated, - isVideo = _isVideo, - thumbnail = _thumbnail, - emoji = _emoji, - setName = _setName, - premiumAnimation = _premiumAnimation, - maskPosition = _maskPosition, - customEmojiId = _customEmojiId, - needsRepainting = _needsRepainting, - fileSize = _fileSize - ) - } - } - - implicit lazy val messageEncoder: Encoder[Message] = - (x: Message) => { - Json.fromFields( - List( - "message_id" -> x.messageId.asJson, - "message_thread_id" -> x.messageThreadId.asJson, - "from" -> x.from.asJson, - "sender_chat" -> x.senderChat.asJson, - "date" -> x.date.asJson, - "chat" -> x.chat.asJson, - "forward_from" -> x.forwardFrom.asJson, - "forward_from_chat" -> x.forwardFromChat.asJson, - "forward_from_message_id" -> x.forwardFromMessageId.asJson, - "forward_signature" -> x.forwardSignature.asJson, - "forward_sender_name" -> x.forwardSenderName.asJson, - "forward_date" -> x.forwardDate.asJson, - "is_topic_message" -> x.isTopicMessage.asJson, - "is_automatic_forward" -> x.isAutomaticForward.asJson, - "reply_to_message" -> x.replyToMessage.asJson, - "via_bot" -> x.viaBot.asJson, - "edit_date" -> x.editDate.asJson, - "has_protected_content" -> x.hasProtectedContent.asJson, - "media_group_id" -> x.mediaGroupId.asJson, - "author_signature" -> x.authorSignature.asJson, - "text" -> x.text.asJson, - "entities" -> x.entities.asJson, - "animation" -> x.animation.asJson, - "audio" -> x.audio.asJson, - "document" -> x.document.asJson, - "photo" -> x.photo.asJson, - "sticker" -> x.sticker.asJson, - "story" -> x.story.asJson, - "video" -> x.video.asJson, - "video_note" -> x.videoNote.asJson, - "voice" -> x.voice.asJson, - "caption" -> x.caption.asJson, - "caption_entities" -> x.captionEntities.asJson, - "has_media_spoiler" -> x.hasMediaSpoiler.asJson, - "contact" -> x.contact.asJson, - "dice" -> x.dice.asJson, - "game" -> x.game.asJson, - "poll" -> x.poll.asJson, - "venue" -> x.venue.asJson, - "location" -> x.location.asJson, - "new_chat_members" -> x.newChatMembers.asJson, - "left_chat_member" -> x.leftChatMember.asJson, - "new_chat_title" -> x.newChatTitle.asJson, - "new_chat_photo" -> x.newChatPhoto.asJson, - "delete_chat_photo" -> x.deleteChatPhoto.asJson, - "group_chat_created" -> x.groupChatCreated.asJson, - "supergroup_chat_created" -> x.supergroupChatCreated.asJson, - "channel_chat_created" -> x.channelChatCreated.asJson, - "message_auto_delete_timer_changed" -> x.messageAutoDeleteTimerChanged.asJson, - "migrate_to_chat_id" -> x.migrateToChatId.asJson, - "migrate_from_chat_id" -> x.migrateFromChatId.asJson, - "pinned_message" -> x.pinnedMessage.asJson, - "invoice" -> x.invoice.asJson, - "successful_payment" -> x.successfulPayment.asJson, - "user_shared" -> x.userShared.asJson, - "chat_shared" -> x.chatShared.asJson, - "connected_website" -> x.connectedWebsite.asJson, - "write_access_allowed" -> x.writeAccessAllowed.asJson, - "passport_data" -> x.passportData.asJson, - "proximity_alert_triggered" -> x.proximityAlertTriggered.asJson, - "forum_topic_created" -> x.forumTopicCreated.asJson, - "forum_topic_edited" -> x.forumTopicEdited.asJson, - "forum_topic_closed" -> x.forumTopicClosed.asJson, - "forum_topic_reopened" -> x.forumTopicReopened.asJson, - "general_forum_topic_hidden" -> x.generalForumTopicHidden.asJson, - "general_forum_topic_unhidden" -> x.generalForumTopicUnhidden.asJson, - "video_chat_scheduled" -> x.videoChatScheduled.asJson, - "video_chat_started" -> x.videoChatStarted.asJson, - "video_chat_ended" -> x.videoChatEnded.asJson, - "video_chat_participants_invited" -> x.videoChatParticipantsInvited.asJson, - "web_app_data" -> x.webAppData.asJson, - "reply_markup" -> x.replyMarkup.asJson + "needs_repainting" -> x.needsRepainting.asJson, + "file_size" -> x.fileSize.asJson ).filter(!_._2.isNull) ) } - implicit lazy val messageDecoder: Decoder[Message] = + implicit lazy val stickerDecoder: Decoder[Sticker] = Decoder.instance { h => for { - _messageId <- h.get[Int]("message_id") - _messageThreadId <- h.get[Option[Int]]("message_thread_id") - _from <- h.get[Option[User]]("from") - _senderChat <- h.get[Option[Chat]]("sender_chat") - _date <- h.get[Int]("date") - _chat <- h.get[Chat]("chat") - _forwardFrom <- h.get[Option[User]]("forward_from") - _forwardFromChat <- h.get[Option[Chat]]("forward_from_chat") - _forwardFromMessageId <- h.get[Option[Int]]("forward_from_message_id") - _forwardSignature <- h.get[Option[String]]("forward_signature") - _forwardSenderName <- h.get[Option[String]]("forward_sender_name") - _forwardDate <- h.get[Option[Int]]("forward_date") - _isTopicMessage <- h.get[Option[Boolean]]("is_topic_message") - _isAutomaticForward <- h.get[Option[Boolean]]("is_automatic_forward") - _replyToMessage <- h.get[Option[Message]]("reply_to_message") - _viaBot <- h.get[Option[User]]("via_bot") - _editDate <- h.get[Option[Int]]("edit_date") - _hasProtectedContent <- h.get[Option[Boolean]]("has_protected_content") - _mediaGroupId <- h.get[Option[String]]("media_group_id") - _authorSignature <- h.get[Option[String]]("author_signature") - _text <- h.get[Option[String]]("text") - _entities <- h.getOrElse[List[MessageEntity]]("entities")(List.empty) - _animation <- h.get[Option[Animation]]("animation") - _audio <- h.get[Option[Audio]]("audio") - _document <- h.get[Option[Document]]("document") - _photo <- h.getOrElse[List[PhotoSize]]("photo")(List.empty) - _sticker <- h.get[Option[Sticker]]("sticker") - _story <- h.get[Option[Story.type]]("story") - _video <- h.get[Option[Video]]("video") - _videoNote <- h.get[Option[VideoNote]]("video_note") - _voice <- h.get[Option[Voice]]("voice") - _caption <- h.get[Option[String]]("caption") - _captionEntities <- h.getOrElse[List[MessageEntity]]("caption_entities")(List.empty) - _hasMediaSpoiler <- h.get[Option[Boolean]]("has_media_spoiler") - _contact <- h.get[Option[Contact]]("contact") - _dice <- h.get[Option[Dice]]("dice") - _game <- h.get[Option[Game]]("game") - _poll <- h.get[Option[Poll]]("poll") - _venue <- h.get[Option[Venue]]("venue") - _location <- h.get[Option[Location]]("location") - _newChatMembers <- h.getOrElse[List[User]]("new_chat_members")(List.empty) - _leftChatMember <- h.get[Option[User]]("left_chat_member") - _newChatTitle <- h.get[Option[String]]("new_chat_title") - _newChatPhoto <- h.getOrElse[List[PhotoSize]]("new_chat_photo")(List.empty) - _deleteChatPhoto <- h.get[Option[Boolean]]("delete_chat_photo") - _groupChatCreated <- h.get[Option[Boolean]]("group_chat_created") - _supergroupChatCreated <- h.get[Option[Boolean]]("supergroup_chat_created") - _channelChatCreated <- h.get[Option[Boolean]]("channel_chat_created") - _messageAutoDeleteTimerChanged <- h.get[Option[MessageAutoDeleteTimerChanged]]( - "message_auto_delete_timer_changed" - ) - _migrateToChatId <- h.get[Option[Long]]("migrate_to_chat_id") - _migrateFromChatId <- h.get[Option[Long]]("migrate_from_chat_id") - _pinnedMessage <- h.get[Option[Message]]("pinned_message") - _invoice <- h.get[Option[Invoice]]("invoice") - _successfulPayment <- h.get[Option[SuccessfulPayment]]("successful_payment") - _userShared <- h.get[Option[UserShared]]("user_shared") - _chatShared <- h.get[Option[ChatShared]]("chat_shared") - _connectedWebsite <- h.get[Option[String]]("connected_website") - _writeAccessAllowed <- h.get[Option[WriteAccessAllowed]]("write_access_allowed") - _passportData <- h.get[Option[PassportData]]("passport_data") - _proximityAlertTriggered <- h.get[Option[ProximityAlertTriggered]]("proximity_alert_triggered") - _forumTopicCreated <- h.get[Option[ForumTopicCreated]]("forum_topic_created") - _forumTopicEdited <- h.get[Option[ForumTopicEdited]]("forum_topic_edited") - _forumTopicClosed <- h.get[Option[ForumTopicClosed.type]]("forum_topic_closed") - _forumTopicReopened <- h.get[Option[ForumTopicReopened.type]]("forum_topic_reopened") - _generalForumTopicHidden <- h.get[Option[GeneralForumTopicHidden.type]]("general_forum_topic_hidden") - _generalForumTopicUnhidden <- h.get[Option[GeneralForumTopicUnhidden.type]]("general_forum_topic_unhidden") - _videoChatScheduled <- h.get[Option[VideoChatScheduled]]("video_chat_scheduled") - _videoChatStarted <- h.get[Option[VideoChatStarted.type]]("video_chat_started") - _videoChatEnded <- h.get[Option[VideoChatEnded]]("video_chat_ended") - _videoChatParticipantsInvited <- h.get[Option[VideoChatParticipantsInvited]]("video_chat_participants_invited") - _webAppData <- h.get[Option[WebAppData]]("web_app_data") - _replyMarkup <- h.get[Option[InlineKeyboardMarkup]]("reply_markup") + _fileId <- h.get[String]("file_id") + _fileUniqueId <- h.get[String]("file_unique_id") + _type <- h.get[String]("type") + _width <- h.get[Int]("width") + _height <- h.get[Int]("height") + _isAnimated <- h.get[Boolean]("is_animated") + _isVideo <- h.get[Boolean]("is_video") + _thumbnail <- h.get[Option[PhotoSize]]("thumbnail") + _emoji <- h.get[Option[String]]("emoji") + _setName <- h.get[Option[String]]("set_name") + _premiumAnimation <- h.get[Option[File]]("premium_animation") + _maskPosition <- h.get[Option[MaskPosition]]("mask_position") + _customEmojiId <- h.get[Option[String]]("custom_emoji_id") + _needsRepainting <- h.get[Option[Boolean]]("needs_repainting") + _fileSize <- h.get[Option[Long]]("file_size") } yield { - Message( - messageId = _messageId, - messageThreadId = _messageThreadId, - from = _from, - senderChat = _senderChat, - date = _date, - chat = _chat, - forwardFrom = _forwardFrom, - forwardFromChat = _forwardFromChat, - forwardFromMessageId = _forwardFromMessageId, - forwardSignature = _forwardSignature, - forwardSenderName = _forwardSenderName, - forwardDate = _forwardDate, - isTopicMessage = _isTopicMessage, - isAutomaticForward = _isAutomaticForward, - replyToMessage = _replyToMessage, - viaBot = _viaBot, - editDate = _editDate, - hasProtectedContent = _hasProtectedContent, - mediaGroupId = _mediaGroupId, - authorSignature = _authorSignature, - text = _text, - entities = _entities, - animation = _animation, - audio = _audio, - document = _document, - photo = _photo, - sticker = _sticker, - story = _story, - video = _video, - videoNote = _videoNote, - voice = _voice, - caption = _caption, - captionEntities = _captionEntities, - hasMediaSpoiler = _hasMediaSpoiler, - contact = _contact, - dice = _dice, - game = _game, - poll = _poll, - venue = _venue, - location = _location, - newChatMembers = _newChatMembers, - leftChatMember = _leftChatMember, - newChatTitle = _newChatTitle, - newChatPhoto = _newChatPhoto, - deleteChatPhoto = _deleteChatPhoto, - groupChatCreated = _groupChatCreated, - supergroupChatCreated = _supergroupChatCreated, - channelChatCreated = _channelChatCreated, - messageAutoDeleteTimerChanged = _messageAutoDeleteTimerChanged, - migrateToChatId = _migrateToChatId, - migrateFromChatId = _migrateFromChatId, - pinnedMessage = _pinnedMessage, - invoice = _invoice, - successfulPayment = _successfulPayment, - userShared = _userShared, - chatShared = _chatShared, - connectedWebsite = _connectedWebsite, - writeAccessAllowed = _writeAccessAllowed, - passportData = _passportData, - proximityAlertTriggered = _proximityAlertTriggered, - forumTopicCreated = _forumTopicCreated, - forumTopicEdited = _forumTopicEdited, - forumTopicClosed = _forumTopicClosed, - forumTopicReopened = _forumTopicReopened, - generalForumTopicHidden = _generalForumTopicHidden, - generalForumTopicUnhidden = _generalForumTopicUnhidden, - videoChatScheduled = _videoChatScheduled, - videoChatStarted = _videoChatStarted, - videoChatEnded = _videoChatEnded, - videoChatParticipantsInvited = _videoChatParticipantsInvited, - webAppData = _webAppData, - replyMarkup = _replyMarkup + Sticker( + fileId = _fileId, + fileUniqueId = _fileUniqueId, + `type` = _type, + width = _width, + height = _height, + isAnimated = _isAnimated, + isVideo = _isVideo, + thumbnail = _thumbnail, + emoji = _emoji, + setName = _setName, + premiumAnimation = _premiumAnimation, + maskPosition = _maskPosition, + customEmojiId = _customEmojiId, + needsRepainting = _needsRepainting, + fileSize = _fileSize ) } } @@ -4966,6 +5683,44 @@ object CirceImplicits { } } + implicit lazy val reactioncountEncoder: Encoder[ReactionCount] = + (x: ReactionCount) => { + Json.fromFields( + List( + "type" -> x.`type`.asJson, + "total_count" -> x.totalCount.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val reactioncountDecoder: Decoder[ReactionCount] = + Decoder.instance { h => + for { + _type <- h.get[ReactionType]("type") + _totalCount <- h.get[Int]("total_count") + } yield { + ReactionCount(`type` = _type, totalCount = _totalCount) + } + } + + implicit lazy val userchatboostsEncoder: Encoder[UserChatBoosts] = + (x: UserChatBoosts) => { + Json.fromFields( + List( + "boosts" -> x.boosts.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val userchatboostsDecoder: Decoder[UserChatBoosts] = + Decoder.instance { h => + for { + _boosts <- h.getOrElse[List[ChatBoost]]("boosts")(List.empty) + } yield { + UserChatBoosts(boosts = _boosts) + } + } + implicit lazy val encryptedcredentialsEncoder: Encoder[EncryptedCredentials] = (x: EncryptedCredentials) => { Json.fromFields( @@ -5035,6 +5790,30 @@ object CirceImplicits { } } + implicit lazy val textquoteEncoder: Encoder[TextQuote] = + (x: TextQuote) => { + Json.fromFields( + List( + "text" -> x.text.asJson, + "entities" -> x.entities.asJson, + "position" -> x.position.asJson, + "is_manual" -> x.isManual.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val textquoteDecoder: Decoder[TextQuote] = + Decoder.instance { h => + for { + _text <- h.get[String]("text") + _entities <- h.getOrElse[List[MessageEntity]]("entities")(List.empty) + _position <- h.get[Int]("position") + _isManual <- h.get[Option[Boolean]]("is_manual") + } yield { + TextQuote(text = _text, entities = _entities, position = _position, isManual = _isManual) + } + } + implicit lazy val loginurlEncoder: Encoder[LoginUrl] = (x: LoginUrl) => { Json.fromFields( @@ -5139,7 +5918,7 @@ object CirceImplicits { for { _id <- h.get[String]("id") _from <- h.get[User]("from") - _message <- h.get[Option[Message]]("message") + _message <- h.get[Option[MaybeInaccessibleMessage]]("message") _inlineMessageId <- h.get[Option[String]]("inline_message_id") _chatInstance <- h.get[String]("chat_instance") _data <- h.get[Option[String]]("data") @@ -5157,28 +5936,6 @@ object CirceImplicits { } } - implicit lazy val keyboardbuttonrequestuserEncoder: Encoder[KeyboardButtonRequestUser] = - (x: KeyboardButtonRequestUser) => { - Json.fromFields( - List( - "request_id" -> x.requestId.asJson, - "user_is_bot" -> x.userIsBot.asJson, - "user_is_premium" -> x.userIsPremium.asJson - ).filter(!_._2.isNull) - ) - } - - implicit lazy val keyboardbuttonrequestuserDecoder: Decoder[KeyboardButtonRequestUser] = - Decoder.instance { h => - for { - _requestId <- h.get[Int]("request_id") - _userIsBot <- h.get[Option[Boolean]]("user_is_bot") - _userIsPremium <- h.get[Option[Boolean]]("user_is_premium") - } yield { - KeyboardButtonRequestUser(requestId = _requestId, userIsBot = _userIsBot, userIsPremium = _userIsPremium) - } - } - implicit lazy val chatsharedEncoder: Encoder[ChatShared] = (x: ChatShared) => { Json.fromFields( @@ -5217,6 +5974,68 @@ object CirceImplicits { } } + implicit lazy val messagereactioncountupdatedEncoder: Encoder[MessageReactionCountUpdated] = + (x: MessageReactionCountUpdated) => { + Json.fromFields( + List( + "chat" -> x.chat.asJson, + "message_id" -> x.messageId.asJson, + "date" -> x.date.asJson, + "reactions" -> x.reactions.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val messagereactioncountupdatedDecoder: Decoder[MessageReactionCountUpdated] = + Decoder.instance { h => + for { + _chat <- h.get[Chat]("chat") + _messageId <- h.get[Int]("message_id") + _date <- h.get[Int]("date") + _reactions <- h.getOrElse[List[ReactionCount]]("reactions")(List.empty) + } yield { + MessageReactionCountUpdated(chat = _chat, messageId = _messageId, date = _date, reactions = _reactions) + } + } + + implicit lazy val messagereactionupdatedEncoder: Encoder[MessageReactionUpdated] = + (x: MessageReactionUpdated) => { + Json.fromFields( + List( + "chat" -> x.chat.asJson, + "message_id" -> x.messageId.asJson, + "user" -> x.user.asJson, + "actor_chat" -> x.actorChat.asJson, + "date" -> x.date.asJson, + "old_reaction" -> x.oldReaction.asJson, + "new_reaction" -> x.newReaction.asJson + ).filter(!_._2.isNull) + ) + } + + implicit lazy val messagereactionupdatedDecoder: Decoder[MessageReactionUpdated] = + Decoder.instance { h => + for { + _chat <- h.get[Chat]("chat") + _messageId <- h.get[Int]("message_id") + _user <- h.get[Option[User]]("user") + _actorChat <- h.get[Option[Chat]]("actor_chat") + _date <- h.get[Int]("date") + _oldReaction <- h.getOrElse[List[ReactionType]]("old_reaction")(List.empty) + _newReaction <- h.getOrElse[List[ReactionType]]("new_reaction")(List.empty) + } yield { + MessageReactionUpdated( + chat = _chat, + messageId = _messageId, + user = _user, + actorChat = _actorChat, + date = _date, + oldReaction = _oldReaction, + newReaction = _newReaction + ) + } + } + implicit lazy val forumtopiccreatedEncoder: Encoder[ForumTopicCreated] = (x: ForumTopicCreated) => { Json.fromFields( diff --git a/telegramium-examples/src/main/scala/telegramium/bots/examples/EchoBot.scala b/telegramium-examples/src/main/scala/telegramium/bots/examples/EchoBot.scala index 39d66d3f..0c2982a0 100644 --- a/telegramium-examples/src/main/scala/telegramium/bots/examples/EchoBot.scala +++ b/telegramium-examples/src/main/scala/telegramium/bots/examples/EchoBot.scala @@ -48,6 +48,9 @@ class EchoBot[F[_]]()(implicit } override def onCallbackQuery(query: CallbackQuery): F[Unit] = { + def onMsg(message: Option[MaybeInaccessibleMessage])(f: Message => F[Unit]): F[Unit] = + message.collect { case m: Message => m }.fold(asyncF.unit)(f) + def rollTheDice(chatId: Long, emoji: Emoji = EmojiDice): F[Unit] = { sendDice(ChatIntId(chatId), emoji = Some(emoji.toString)).exec.void >> answerCallbackQuery(callbackQueryId = query.id).exec.void @@ -81,13 +84,14 @@ class EchoBot[F[_]]()(implicit query.data .map { - case "HTML" => query.message.fold(asyncF.unit)(m => sendMsg(m.chat.id, htmlText, Html)) - case "Markdown" => query.message.fold(asyncF.unit)(m => sendMsg(m.chat.id, markdownText, Markdown)) - case "Markdown2" => query.message.fold(asyncF.unit)(m => sendMsg(m.chat.id, markdown2Text, Markdown2)) - case "dice" => query.message.fold(asyncF.unit)(m => rollTheDice(m.chat.id)) - case "darts" => query.message.fold(asyncF.unit)(m => rollTheDice(m.chat.id, EmojiDarts)) - case "basketball" => query.message.fold(asyncF.unit)(m => rollTheDice(m.chat.id, EmojiBasketball)) - case "quiz" => query.message.fold(asyncF.unit)(m => quiz(m.chat.id)) + case "" => onMsg(query.message)(m => sendMsg(m.chat.id, htmlText, Html)) + case "HTML" => onMsg(query.message)(m => sendMsg(m.chat.id, htmlText, Html)) + case "Markdown" => onMsg(query.message)(m => sendMsg(m.chat.id, markdownText, Markdown)) + case "Markdown2" => onMsg(query.message)(m => sendMsg(m.chat.id, markdown2Text, Markdown2)) + case "dice" => onMsg(query.message)(m => rollTheDice(m.chat.id)) + case "darts" => onMsg(query.message)(m => rollTheDice(m.chat.id, EmojiDarts)) + case "basketball" => onMsg(query.message)(m => rollTheDice(m.chat.id, EmojiBasketball)) + case "quiz" => onMsg(query.message)(m => quiz(m.chat.id)) case x => answerCallbackQuery( callbackQueryId = query.id, diff --git a/telegramium-examples/src/main/scala/telegramium/bots/examples/IceCreamParlorBot.scala b/telegramium-examples/src/main/scala/telegramium/bots/examples/IceCreamParlorBot.scala index bd62afa7..6ba1e536 100644 --- a/telegramium-examples/src/main/scala/telegramium/bots/examples/IceCreamParlorBot.scala +++ b/telegramium-examples/src/main/scala/telegramium/bots/examples/IceCreamParlorBot.scala @@ -44,19 +44,20 @@ class IceCreamParlorBot[F[_]]()(implicit override def onCallbackQuery(query: CallbackQuery): F[Unit] = query.data .flatMap { flavor => - query.message.map { msg => - answerCallbackQuery(callbackQueryId = query.id).exec >> - editMessageReplyMarkup( - chatId = Some(ChatIntId(msg.chat.id)), - messageId = Some(msg.messageId), - replyMarkup = None - ).exec >> - editMessageText( - chatId = Some(ChatIntId(msg.chat.id)), - messageId = Some(msg.messageId), - text = s"You have chosen: $flavor" - ).exec.void - } + query.message + .collect { case msg: Message => + answerCallbackQuery(callbackQueryId = query.id).exec >> + editMessageReplyMarkup( + chatId = Some(ChatIntId(msg.chat.id)), + messageId = Some(msg.messageId), + replyMarkup = None + ).exec >> + editMessageText( + chatId = Some(ChatIntId(msg.chat.id)), + messageId = Some(msg.messageId), + text = s"You have chosen: $flavor" + ).exec.void + } } .getOrElse(asyncF.unit) diff --git a/telegramium-high/src/main/scala/telegramium/bots/high/LongPollBot.scala b/telegramium-high/src/main/scala/telegramium/bots/high/LongPollBot.scala index d5f62528..02532260 100644 --- a/telegramium-high/src/main/scala/telegramium/bots/high/LongPollBot.scala +++ b/telegramium-high/src/main/scala/telegramium/bots/high/LongPollBot.scala @@ -18,20 +18,24 @@ abstract class LongPollBot[F[_]: Parallel: Async](bot: Api[F]) extends Methods { private def noop[A](a: A) = Monad[F].pure(a).void - def onMessage(msg: Message): F[Unit] = noop(msg) - def onEditedMessage(msg: Message): F[Unit] = noop(msg) - def onChannelPost(msg: Message): F[Unit] = noop(msg) - def onEditedChannelPost(msg: Message): F[Unit] = noop(msg) - def onInlineQuery(query: InlineQuery): F[Unit] = noop(query) - def onCallbackQuery(query: CallbackQuery): F[Unit] = noop(query) - def onChosenInlineResult(inlineResult: ChosenInlineResult): F[Unit] = noop(inlineResult) - def onShippingQuery(query: ShippingQuery): F[Unit] = noop(query) - def onPreCheckoutQuery(query: PreCheckoutQuery): F[Unit] = noop(query) - def onPoll(poll: Poll): F[Unit] = noop(poll) - def onPollAnswer(pollAnswer: PollAnswer): F[Unit] = noop(pollAnswer) - def onMyChatMember(myChatMember: ChatMemberUpdated): F[Unit] = noop(myChatMember) - def onChatMember(chatMember: ChatMemberUpdated): F[Unit] = noop(chatMember) - def onChatJoinRequest(request: ChatJoinRequest): F[Unit] = noop(request) + def onMessage(msg: Message): F[Unit] = noop(msg) + def onEditedMessage(msg: Message): F[Unit] = noop(msg) + def onChannelPost(msg: Message): F[Unit] = noop(msg) + def onEditedChannelPost(msg: Message): F[Unit] = noop(msg) + def onMessageReaction(reaction: MessageReactionUpdated): F[Unit] = noop(reaction) + def onMessageReactionCount(count: MessageReactionCountUpdated): F[Unit] = noop(count) + def onInlineQuery(query: InlineQuery): F[Unit] = noop(query) + def onCallbackQuery(query: CallbackQuery): F[Unit] = noop(query) + def onChosenInlineResult(inlineResult: ChosenInlineResult): F[Unit] = noop(inlineResult) + def onShippingQuery(query: ShippingQuery): F[Unit] = noop(query) + def onPreCheckoutQuery(query: PreCheckoutQuery): F[Unit] = noop(query) + def onPoll(poll: Poll): F[Unit] = noop(poll) + def onPollAnswer(pollAnswer: PollAnswer): F[Unit] = noop(pollAnswer) + def onMyChatMember(myChatMember: ChatMemberUpdated): F[Unit] = noop(myChatMember) + def onChatMember(chatMember: ChatMemberUpdated): F[Unit] = noop(chatMember) + def onChatJoinRequest(request: ChatJoinRequest): F[Unit] = noop(request) + def onChatBoost(boost: ChatBoostUpdated): F[Unit] = noop(boost) + def onRemovedChatBoost(boostRemoved: ChatBoostRemoved): F[Unit] = noop(boostRemoved) def onUpdate(update: Update): F[Unit] = for { @@ -39,6 +43,8 @@ abstract class LongPollBot[F[_]: Parallel: Async](bot: Api[F]) extends Methods { _ <- update.editedMessage.fold(Monad[F].unit)(onEditedMessage) _ <- update.channelPost.fold(Monad[F].unit)(onChannelPost) _ <- update.editedChannelPost.fold(Monad[F].unit)(onEditedChannelPost) + _ <- update.messageReaction.fold(Monad[F].unit)(onMessageReaction) + _ <- update.messageReactionCount.fold(Monad[F].unit)(onMessageReactionCount) _ <- update.inlineQuery.fold(Monad[F].unit)(onInlineQuery) _ <- update.callbackQuery.fold(Monad[F].unit)(onCallbackQuery) _ <- update.chosenInlineResult.fold(Monad[F].unit)(onChosenInlineResult) @@ -49,6 +55,8 @@ abstract class LongPollBot[F[_]: Parallel: Async](bot: Api[F]) extends Methods { _ <- update.myChatMember.fold(Monad[F].unit)(onMyChatMember) _ <- update.chatMember.fold(Monad[F].unit)(onChatMember) _ <- update.chatJoinRequest.fold(Monad[F].unit)(onChatJoinRequest) + _ <- update.chatBoost.fold(Monad[F].unit)(onChatBoost) + _ <- update.removedChatBoost.fold(Monad[F].unit)(onRemovedChatBoost) } yield () def onError(e: Throwable): F[Unit] = { diff --git a/telegramium-high/src/main/scala/telegramium/bots/high/WebhookBot.scala b/telegramium-high/src/main/scala/telegramium/bots/high/WebhookBot.scala index beea2c0f..c5493ba6 100644 --- a/telegramium-high/src/main/scala/telegramium/bots/high/WebhookBot.scala +++ b/telegramium-high/src/main/scala/telegramium/bots/high/WebhookBot.scala @@ -25,6 +25,8 @@ import org.http4s.server.Server import org.http4s.server.inDefaultServiceErrorHandler import telegramium.bots.CallbackQuery +import telegramium.bots.ChatBoostRemoved +import telegramium.bots.ChatBoostUpdated import telegramium.bots.ChatJoinRequest import telegramium.bots.ChatMemberUpdated import telegramium.bots.ChosenInlineResult @@ -32,6 +34,8 @@ import telegramium.bots.CirceImplicits.* import telegramium.bots.InlineQuery import telegramium.bots.InputPartFile import telegramium.bots.Message +import telegramium.bots.MessageReactionCountUpdated +import telegramium.bots.MessageReactionUpdated import telegramium.bots.Poll import telegramium.bots.PollAnswer import telegramium.bots.PreCheckoutQuery @@ -76,40 +80,46 @@ abstract class WebhookBot[F[_]: Async]( private def noop[A](a: A) = Monad[F].pure(a).void - def onMessage(msg: Message): F[Unit] = noop(msg) - def onEditedMessage(msg: Message): F[Unit] = noop(msg) - def onChannelPost(msg: Message): F[Unit] = noop(msg) - def onEditedChannelPost(msg: Message): F[Unit] = noop(msg) - def onInlineQuery(query: InlineQuery): F[Unit] = noop(query) - def onCallbackQuery(query: CallbackQuery): F[Unit] = noop(query) - def onChosenInlineResult(inlineResult: ChosenInlineResult): F[Unit] = noop(inlineResult) - def onShippingQuery(query: ShippingQuery): F[Unit] = noop(query) - def onPreCheckoutQuery(query: PreCheckoutQuery): F[Unit] = noop(query) - def onPoll(poll: Poll): F[Unit] = noop(poll) - def onPollAnswer(pollAnswer: PollAnswer): F[Unit] = noop(pollAnswer) - def onMyChatMember(myChatMember: ChatMemberUpdated): F[Unit] = noop(myChatMember) - def onChatMember(chatMember: ChatMemberUpdated): F[Unit] = noop(chatMember) - def onChatJoinRequest(request: ChatJoinRequest): F[Unit] = noop(request) + def onMessage(msg: Message): F[Unit] = noop(msg) + def onEditedMessage(msg: Message): F[Unit] = noop(msg) + def onChannelPost(msg: Message): F[Unit] = noop(msg) + def onEditedChannelPost(msg: Message): F[Unit] = noop(msg) + def onMessageReaction(reaction: MessageReactionUpdated): F[Unit] = noop(reaction) + def onMessageReactionCount(count: MessageReactionCountUpdated): F[Unit] = noop(count) + def onInlineQuery(query: InlineQuery): F[Unit] = noop(query) + def onCallbackQuery(query: CallbackQuery): F[Unit] = noop(query) + def onChosenInlineResult(inlineResult: ChosenInlineResult): F[Unit] = noop(inlineResult) + def onShippingQuery(query: ShippingQuery): F[Unit] = noop(query) + def onPreCheckoutQuery(query: PreCheckoutQuery): F[Unit] = noop(query) + def onPoll(poll: Poll): F[Unit] = noop(poll) + def onPollAnswer(pollAnswer: PollAnswer): F[Unit] = noop(pollAnswer) + def onMyChatMember(myChatMember: ChatMemberUpdated): F[Unit] = noop(myChatMember) + def onChatMember(chatMember: ChatMemberUpdated): F[Unit] = noop(chatMember) + def onChatJoinRequest(request: ChatJoinRequest): F[Unit] = noop(request) + def onChatBoost(boost: ChatBoostUpdated): F[Unit] = noop(boost) + def onRemovedChatBoost(boostRemoved: ChatBoostRemoved): F[Unit] = noop(boostRemoved) private def noopReply[A](a: A) = Monad[F].pure(a).map(_ => Option.empty[Method[?]]) - def onMessageReply(msg: Message): F[Option[Method[?]]] = noopReply(msg) - def onEditedMessageReply(msg: Message): F[Option[Method[?]]] = noopReply(msg) - def onChannelPostReply(msg: Message): F[Option[Method[?]]] = noopReply(msg) - def onEditedChannelPostReply(msg: Message): F[Option[Method[?]]] = noopReply(msg) - def onInlineQueryReply(query: InlineQuery): F[Option[Method[?]]] = noopReply(query) - def onCallbackQueryReply(query: CallbackQuery): F[Option[Method[?]]] = noopReply(query) - + def onMessageReply(msg: Message): F[Option[Method[?]]] = noopReply(msg) + def onEditedMessageReply(msg: Message): F[Option[Method[?]]] = noopReply(msg) + def onChannelPostReply(msg: Message): F[Option[Method[?]]] = noopReply(msg) + def onEditedChannelPostReply(msg: Message): F[Option[Method[?]]] = noopReply(msg) + def onMessageReactionReply(reaction: MessageReactionUpdated): F[Option[Method[?]]] = noopReply(reaction) + def onMessageReactionCountReply(count: MessageReactionCountUpdated): F[Option[Method[?]]] = noopReply(count) + def onInlineQueryReply(query: InlineQuery): F[Option[Method[?]]] = noopReply(query) + def onCallbackQueryReply(query: CallbackQuery): F[Option[Method[?]]] = noopReply(query) def onChosenInlineResultReply(inlineResult: ChosenInlineResult): F[Option[Method[?]]] = Monad[F].pure(inlineResult).map(_ => Option.empty[Method[?]]) - - def onShippingQueryReply(query: ShippingQuery): F[Option[Method[?]]] = noopReply(query) - def onPreCheckoutQueryReply(query: PreCheckoutQuery): F[Option[Method[?]]] = noopReply(query) - def onPollReply(poll: Poll): F[Option[Method[?]]] = noopReply(poll) - def onPollAnswerReply(pollAnswer: PollAnswer): F[Option[Method[?]]] = noopReply(pollAnswer) - def onMyChatMemberReply(myChatMember: ChatMemberUpdated): F[Option[Method[?]]] = noopReply(myChatMember) - def onChatMemberReply(chatMember: ChatMemberUpdated): F[Option[Method[?]]] = noopReply(chatMember) - def onChatJoinRequestReply(request: ChatJoinRequest): F[Option[Method[?]]] = noopReply(request) + def onShippingQueryReply(query: ShippingQuery): F[Option[Method[?]]] = noopReply(query) + def onPreCheckoutQueryReply(query: PreCheckoutQuery): F[Option[Method[?]]] = noopReply(query) + def onPollReply(poll: Poll): F[Option[Method[?]]] = noopReply(poll) + def onPollAnswerReply(pollAnswer: PollAnswer): F[Option[Method[?]]] = noopReply(pollAnswer) + def onMyChatMemberReply(myChatMember: ChatMemberUpdated): F[Option[Method[?]]] = noopReply(myChatMember) + def onChatMemberReply(chatMember: ChatMemberUpdated): F[Option[Method[?]]] = noopReply(chatMember) + def onChatJoinRequestReply(request: ChatJoinRequest): F[Option[Method[?]]] = noopReply(request) + def onChatBoostReply(boost: ChatBoostUpdated): F[Option[Method[?]]] = noopReply(boost) + def onRemovedChatBoostReply(boostRemoved: ChatBoostRemoved): F[Option[Method[?]]] = noopReply(boostRemoved) def onUpdate(update: Update): F[Option[Method[?]]] = List( @@ -117,6 +127,8 @@ abstract class WebhookBot[F[_]: Async]( update.editedMessage.map(msg => onEditedMessageReply(msg) <* onEditedMessage(msg)), update.channelPost.map(msg => onChannelPostReply(msg) <* onChannelPost(msg)), update.editedChannelPost.map(msg => onEditedChannelPostReply(msg) <* onEditedChannelPost(msg)), + update.messageReaction.map(reaction => onMessageReactionReply(reaction) <* onMessageReaction(reaction)), + update.messageReactionCount.map(count => onMessageReactionCountReply(count) <* onMessageReactionCount(count)), update.inlineQuery.map(query => onInlineQueryReply(query) <* onInlineQuery(query)), update.callbackQuery.map(query => onCallbackQueryReply(query) <* onCallbackQuery(query)), update.chosenInlineResult.map(inlineResult => @@ -128,7 +140,11 @@ abstract class WebhookBot[F[_]: Async]( update.pollAnswer.map(pollAnswer => onPollAnswerReply(pollAnswer) <* onPollAnswer(pollAnswer)), update.myChatMember.map(myChatMember => onMyChatMemberReply(myChatMember) <* onMyChatMember(myChatMember)), update.chatMember.map(chatMember => onChatMemberReply(chatMember) <* onChatMember(chatMember)), - update.chatJoinRequest.map(request => onChatJoinRequestReply(request) <* onChatJoinRequest(request)) + update.chatJoinRequest.map(request => onChatJoinRequestReply(request) <* onChatJoinRequest(request)), + update.chatBoost.map(boost => onChatBoostReply(boost) <* onChatBoost(boost)), + update.removedChatBoost.map(boostRemoved => + onRemovedChatBoostReply(boostRemoved) <* onRemovedChatBoost(boostRemoved) + ) ).flatten.head private implicit val HandleUpdateReqEntityDecoder: EntityDecoder[F, Update] = jsonOf[F, Update] diff --git a/telegramium-high/src/main/scala/telegramium/bots/high/keyboards/KeyboardButtons.scala b/telegramium-high/src/main/scala/telegramium/bots/high/keyboards/KeyboardButtons.scala index 43934040..1750f371 100644 --- a/telegramium-high/src/main/scala/telegramium/bots/high/keyboards/KeyboardButtons.scala +++ b/telegramium-high/src/main/scala/telegramium/bots/high/keyboards/KeyboardButtons.scala @@ -3,7 +3,7 @@ package telegramium.bots.high.keyboards import telegramium.bots.KeyboardButton import telegramium.bots.KeyboardButtonPollType import telegramium.bots.KeyboardButtonRequestChat -import telegramium.bots.KeyboardButtonRequestUser +import telegramium.bots.KeyboardButtonRequestUsers import telegramium.bots.WebAppInfo object KeyboardButtons { @@ -28,8 +28,8 @@ object KeyboardButtons { /** Pressing the button will open a list of suitable users. Tapping on any user will send their identifier to the bot * in a “user_shared” service message. */ - def requestUser(text: String, requestUser: KeyboardButtonRequestUser) = - KeyboardButton(text, requestUser = Some(requestUser)) + def requestUsers(text: String, requestUsers: KeyboardButtonRequestUsers) = + KeyboardButton(text, requestUsers = Some(requestUsers)) /** Pressing the button will open a list of suitable chats. Tapping on a chat will send its identifier to the bot in a * “chat_shared” service message. diff --git a/telegramium-high/src/main/scala/telegramium/bots/high/messageentities/MessageEntities.scala b/telegramium-high/src/main/scala/telegramium/bots/high/messageentities/MessageEntities.scala index 0c1d5f09..a4c3dc35 100644 --- a/telegramium-high/src/main/scala/telegramium/bots/high/messageentities/MessageEntities.scala +++ b/telegramium-high/src/main/scala/telegramium/bots/high/messageentities/MessageEntities.scala @@ -58,6 +58,7 @@ class MessageEntities(val underlying: Vector[MessageEntityFormat] = Vector.empty def customEmoji(text: String, customEmojiId: String) = add(CustomEmoji(text, customEmojiId)) def spoiler(text: String) = add(Spoiler(text)) def email(text: String): MessageEntities = add(Email(text)) + def blockquote(text: String): MessageEntities = add(Blockquote(text)) def pre(text: String, language: Option[String]): MessageEntities = add(Pre(text, language)) def italic(text: String): MessageEntities = add(Italic(text)) def strikethrough(text: String): MessageEntities = add(Strikethrough(text)) diff --git a/telegramium-high/src/main/scala/telegramium/bots/high/messageentities/MessageEntityFormat.scala b/telegramium-high/src/main/scala/telegramium/bots/high/messageentities/MessageEntityFormat.scala index 2f54698f..8587a4f2 100644 --- a/telegramium-high/src/main/scala/telegramium/bots/high/messageentities/MessageEntityFormat.scala +++ b/telegramium-high/src/main/scala/telegramium/bots/high/messageentities/MessageEntityFormat.scala @@ -1,5 +1,6 @@ package telegramium.bots.high.messageentities +import telegramium.bots.BlockquoteMessageEntity import telegramium.bots.BoldMessageEntity import telegramium.bots.BotCommandMessageEntity import telegramium.bots.CashtagMessageEntity @@ -58,6 +59,7 @@ object MessageEntityFormat { accumulate(CustomEmojiMessageEntity(offset, text.length, customEmojiId)) case Spoiler(text) => accumulate(SpoilerMessageEntity(offset, text.length)) case Email(text) => accumulate(EmailMessageEntity(offset, text.length)) + case Blockquote(text) => accumulate(BlockquoteMessageEntity(offset, text.length)) case Bold(text) => accumulate(BoldMessageEntity(offset, text.length)) case Pre(text, language) => accumulate(PreMessageEntity(offset, text.length, language)) case Italic(text) => accumulate(ItalicMessageEntity(offset, text.length)) @@ -93,6 +95,8 @@ object MessageEntityFormat { final case class Email(text: String) extends MessageEntityFormat + final case class Blockquote(text: String) extends MessageEntityFormat + final case class Bold(text: String) extends MessageEntityFormat final case class Pre(text: String, language: Option[String]) extends MessageEntityFormat @@ -126,6 +130,8 @@ object MessageEntityFormat { def email(args: Any*): Email = Email(build(args: _*)) + def blockquote(args: Any*): Blockquote = Blockquote(build(args: _*)) + def bold(args: Any*): Bold = Bold(build(args: _*)) def italic(args: Any*): Italic = Italic(build(args: _*)) diff --git a/telegramium-high/src/test/scala/telegramium/bots/high/LongPollBotISpec.scala b/telegramium-high/src/test/scala/telegramium/bots/high/LongPollBotISpec.scala index 6bfaafdb..4f66896f 100644 --- a/telegramium-high/src/test/scala/telegramium/bots/high/LongPollBotISpec.scala +++ b/telegramium-high/src/test/scala/telegramium/bots/high/LongPollBotISpec.scala @@ -15,12 +15,18 @@ import org.scalatest.matchers.should.Matchers import telegramium.bots.CallbackQuery import telegramium.bots.Chat +import telegramium.bots.ChatBoost +import telegramium.bots.ChatBoostRemoved +import telegramium.bots.ChatBoostSourcePremium +import telegramium.bots.ChatBoostUpdated import telegramium.bots.ChatJoinRequest import telegramium.bots.ChatMemberMember import telegramium.bots.ChatMemberUpdated import telegramium.bots.ChosenInlineResult import telegramium.bots.InlineQuery import telegramium.bots.Message +import telegramium.bots.MessageReactionCountUpdated +import telegramium.bots.MessageReactionUpdated import telegramium.bots.Poll import telegramium.bots.PollAnswer import telegramium.bots.PreCheckoutQuery @@ -46,12 +52,13 @@ class LongPollBotISpec private lazy val bot = new TestLongPollBot(api) private val testUpdate = Update(updateId = 0) - private val testMessage = Message(0, date = 0, chat = Chat(0, `type` = "")) + private val testChat = Chat(0, `type` = "") + private val testMessage = Message(0, date = 0, chat = testChat) private val testUser = User(0, isBot = false, "") private val testChatMemberUpdated = ChatMemberUpdated( - Chat(0, `type` = ""), + testChat, testUser, 0, ChatMemberMember("", testUser), @@ -60,7 +67,7 @@ class LongPollBotISpec private val testChatJoinRequest = ChatJoinRequest( - Chat(0, `type` = ""), + testChat, testUser, 0L, 0 @@ -95,6 +102,28 @@ class LongPollBotISpec bot.onUpdate(testUpdate.copy(editedChannelPost = testMessage.some)).unsafeRunSync() } + "message reaction" in { + mockServerClient + .when(sendMessageRequest("onMessageReaction")) + .respond(sendMessageResponse) + bot + .onUpdate( + testUpdate.copy(messageReaction = MessageReactionUpdated(testChat, 0, 0).some) + ) + .unsafeRunSync() + } + + "message reaction count" in { + mockServerClient + .when(sendMessageRequest("onMessageReactionCount")) + .respond(sendMessageResponse) + bot + .onUpdate( + testUpdate.copy(messageReactionCount = MessageReactionCountUpdated(testChat, 0, 0).some) + ) + .unsafeRunSync() + } + "inline query" in { mockServerClient .when(sendMessageRequest("onInlineQuery")) @@ -189,6 +218,31 @@ class LongPollBotISpec .respond(sendMessageResponse) bot.onUpdate(testUpdate.copy(chatJoinRequest = testChatJoinRequest.some)).unsafeRunSync() } + + "chat boost" in { + mockServerClient + .when(sendMessageRequest("onChatBoost")) + .respond(sendMessageResponse) + bot + .onUpdate( + testUpdate.copy(chatBoost = + ChatBoostUpdated(testChat, ChatBoost("", 0, 0, ChatBoostSourcePremium("", testUser))).some + ) + ) + .unsafeRunSync() + } + + "removed chat boost" in { + mockServerClient + .when(sendMessageRequest("onRemovedChatBoost")) + .respond(sendMessageResponse) + bot + .onUpdate( + testUpdate + .copy(removedChatBoost = ChatBoostRemoved(testChat, "", 0, ChatBoostSourcePremium("", testUser)).some) + ) + .unsafeRunSync() + } } override protected def afterAll(): Unit = { diff --git a/telegramium-high/src/test/scala/telegramium/bots/high/TestLongPollBot.scala b/telegramium-high/src/test/scala/telegramium/bots/high/TestLongPollBot.scala index 78eeaa41..91b645a5 100644 --- a/telegramium-high/src/test/scala/telegramium/bots/high/TestLongPollBot.scala +++ b/telegramium-high/src/test/scala/telegramium/bots/high/TestLongPollBot.scala @@ -3,12 +3,16 @@ package telegramium.bots.high import cats.effect.IO import telegramium.bots.CallbackQuery +import telegramium.bots.ChatBoostRemoved +import telegramium.bots.ChatBoostUpdated import telegramium.bots.ChatIntId import telegramium.bots.ChatJoinRequest import telegramium.bots.ChatMemberUpdated import telegramium.bots.ChosenInlineResult import telegramium.bots.InlineQuery import telegramium.bots.Message +import telegramium.bots.MessageReactionCountUpdated +import telegramium.bots.MessageReactionUpdated import telegramium.bots.Poll import telegramium.bots.PollAnswer import telegramium.bots.PreCheckoutQuery @@ -17,22 +21,26 @@ import telegramium.bots.ShippingQuery class TestLongPollBot(api: Api[IO]) extends LongPollBot[IO](api) { private def sendMessageTask(text: String) = api.execute(sendMessage(ChatIntId(0), text)).void - override def onMessage(msg: Message): IO[Unit] = sendMessageTask("onMessage") - override def onEditedMessage(msg: Message): IO[Unit] = sendMessageTask("onEditedMessage") - override def onChannelPost(msg: Message): IO[Unit] = sendMessageTask("onChannelPost") - override def onEditedChannelPost(msg: Message): IO[Unit] = sendMessageTask("onEditedChannelPost") + override def onMessage(msg: Message): IO[Unit] = sendMessageTask("onMessage") + override def onEditedMessage(msg: Message): IO[Unit] = sendMessageTask("onEditedMessage") + override def onChannelPost(msg: Message): IO[Unit] = sendMessageTask("onChannelPost") + override def onEditedChannelPost(msg: Message): IO[Unit] = sendMessageTask("onEditedChannelPost") + override def onMessageReaction(reaction: MessageReactionUpdated): IO[Unit] = sendMessageTask("onMessageReaction") + override def onMessageReactionCount(count: MessageReactionCountUpdated): IO[Unit] = sendMessageTask( + "onMessageReactionCount" + ) override def onInlineQuery(query: InlineQuery): IO[Unit] = sendMessageTask("onInlineQuery") override def onCallbackQuery(query: CallbackQuery): IO[Unit] = sendMessageTask("onCallbackQuery") - override def onChosenInlineResult(inlineResult: ChosenInlineResult): IO[Unit] = sendMessageTask( "onChosenInlineResult" ) - - override def onShippingQuery(query: ShippingQuery): IO[Unit] = sendMessageTask("onShippingQuery") - override def onPreCheckoutQuery(query: PreCheckoutQuery): IO[Unit] = sendMessageTask("onPreCheckoutQuery") - override def onPoll(poll: Poll): IO[Unit] = sendMessageTask("onPoll") - override def onPollAnswer(pollAnswer: PollAnswer): IO[Unit] = sendMessageTask("onPollAnswer") - override def onMyChatMember(myChatMember: ChatMemberUpdated): IO[Unit] = sendMessageTask("onMyChatMember") - override def onChatMember(chatMember: ChatMemberUpdated): IO[Unit] = sendMessageTask("onChatMember") - override def onChatJoinRequest(request: ChatJoinRequest): IO[Unit] = sendMessageTask("onChatJoinRequest") + override def onShippingQuery(query: ShippingQuery): IO[Unit] = sendMessageTask("onShippingQuery") + override def onPreCheckoutQuery(query: PreCheckoutQuery): IO[Unit] = sendMessageTask("onPreCheckoutQuery") + override def onPoll(poll: Poll): IO[Unit] = sendMessageTask("onPoll") + override def onPollAnswer(pollAnswer: PollAnswer): IO[Unit] = sendMessageTask("onPollAnswer") + override def onMyChatMember(myChatMember: ChatMemberUpdated): IO[Unit] = sendMessageTask("onMyChatMember") + override def onChatMember(chatMember: ChatMemberUpdated): IO[Unit] = sendMessageTask("onChatMember") + override def onChatJoinRequest(request: ChatJoinRequest): IO[Unit] = sendMessageTask("onChatJoinRequest") + override def onChatBoost(boost: ChatBoostUpdated): IO[Unit] = sendMessageTask("onChatBoost") + override def onRemovedChatBoost(boostRemoved: ChatBoostRemoved): IO[Unit] = sendMessageTask("onRemovedChatBoost") } diff --git a/telegramium-high/src/test/scala/telegramium/bots/high/TestWebhookBot.scala b/telegramium-high/src/test/scala/telegramium/bots/high/TestWebhookBot.scala index e4601e77..e83d6c59 100644 --- a/telegramium-high/src/test/scala/telegramium/bots/high/TestWebhookBot.scala +++ b/telegramium-high/src/test/scala/telegramium/bots/high/TestWebhookBot.scala @@ -4,12 +4,16 @@ import cats.effect.IO import cats.syntax.option.* import telegramium.bots.CallbackQuery +import telegramium.bots.ChatBoostRemoved +import telegramium.bots.ChatBoostUpdated import telegramium.bots.ChatIntId import telegramium.bots.ChatJoinRequest import telegramium.bots.ChatMemberUpdated import telegramium.bots.ChosenInlineResult import telegramium.bots.InlineQuery import telegramium.bots.Message +import telegramium.bots.MessageReactionCountUpdated +import telegramium.bots.MessageReactionUpdated import telegramium.bots.Poll import telegramium.bots.PollAnswer import telegramium.bots.PreCheckoutQuery @@ -36,6 +40,12 @@ class TestWebhookBot(api: Api[IO], path: String = "/") override def onEditedChannelPost(msg: Message): IO[Unit] = api.execute(sendMessageMethod("onEditedChannelPost")).void + override def onMessageReaction(reaction: MessageReactionUpdated): IO[Unit] = + api.execute(sendMessageMethod("onMessageReaction")).void + + override def onMessageReactionCount(count: MessageReactionCountUpdated): IO[Unit] = + api.execute(sendMessageMethod("onMessageReactionCount")).void + override def onInlineQuery(query: InlineQuery): IO[Unit] = api.execute(sendMessageMethod("onInlineQuery")).void @@ -66,6 +76,12 @@ class TestWebhookBot(api: Api[IO], path: String = "/") override def onChatJoinRequest(request: ChatJoinRequest): IO[Unit] = api.execute(sendMessageMethod("onChatJoinRequest")).void + override def onChatBoost(boost: ChatBoostUpdated): IO[Unit] = + api.execute(sendMessageMethod("onChatBoost")).void + + override def onRemovedChatBoost(boostRemoved: ChatBoostRemoved): IO[Unit] = + api.execute(sendMessageMethod("onRemovedChatBoost")).void + override def onMessageReply(msg: Message): IO[Option[Method[?]]] = IO.pure(sendMessageMethod("onMessageReply").some) @@ -78,6 +94,12 @@ class TestWebhookBot(api: Api[IO], path: String = "/") override def onEditedChannelPostReply(msg: Message): IO[Option[Method[?]]] = IO.pure(sendMessageMethod("onEditedChannelPostReply").some) + override def onMessageReactionReply(reaction: MessageReactionUpdated): IO[Option[Method[?]]] = + IO.pure(sendMessageMethod("onMessageReactionReply").some) + + override def onMessageReactionCountReply(count: MessageReactionCountUpdated): IO[Option[Method[?]]] = + IO.pure(sendMessageMethod("onMessageReactionCountReply").some) + override def onInlineQueryReply(query: InlineQuery): IO[Option[Method[?]]] = IO.pure(sendMessageMethod("onInlineQueryReply").some) @@ -108,4 +130,10 @@ class TestWebhookBot(api: Api[IO], path: String = "/") override def onChatJoinRequestReply(request: ChatJoinRequest): IO[Option[Method[?]]] = IO.pure(sendMessageMethod("onChatJoinRequestReply").some) + override def onChatBoostReply(boost: ChatBoostUpdated): IO[Option[Method[_]]] = + IO.pure(sendMessageMethod("onChatBoostReply").some) + + override def onRemovedChatBoostReply(boostRemoved: ChatBoostRemoved): IO[Option[Method[_]]] = + IO.pure(sendMessageMethod("onRemovedChatBoostReply").some) + } diff --git a/telegramium-high/src/test/scala/telegramium/bots/high/WebhookBotISpec.scala b/telegramium-high/src/test/scala/telegramium/bots/high/WebhookBotISpec.scala index e78bc87d..10a982ab 100644 --- a/telegramium-high/src/test/scala/telegramium/bots/high/WebhookBotISpec.scala +++ b/telegramium-high/src/test/scala/telegramium/bots/high/WebhookBotISpec.scala @@ -25,6 +25,10 @@ import org.scalatest.matchers.should.Matchers import telegramium.bots.CallbackQuery import telegramium.bots.Chat +import telegramium.bots.ChatBoost +import telegramium.bots.ChatBoostRemoved +import telegramium.bots.ChatBoostSourcePremium +import telegramium.bots.ChatBoostUpdated import telegramium.bots.ChatIntId import telegramium.bots.ChatJoinRequest import telegramium.bots.ChatMemberMember @@ -33,6 +37,8 @@ import telegramium.bots.ChosenInlineResult import telegramium.bots.CirceImplicits.* import telegramium.bots.InlineQuery import telegramium.bots.Message +import telegramium.bots.MessageReactionCountUpdated +import telegramium.bots.MessageReactionUpdated import telegramium.bots.Poll import telegramium.bots.PollAnswer import telegramium.bots.PreCheckoutQuery @@ -61,12 +67,13 @@ class WebhookBotISpec private lazy val bot2 = new TestWebhookBot(api, "/bot2") private val testUpdate = Update(updateId = 0) - private val testMessage = Message(0, date = 0, chat = Chat(0, `type` = "")) + private val testChat = Chat(0, `type` = "") + private val testMessage = Message(0, date = 0, chat = testChat) private val testUser = User(0, isBot = false, "") private val testChatMemberUpdated = ChatMemberUpdated( - Chat(0, `type` = ""), + testChat, testUser, 0, ChatMemberMember("", testUser), @@ -75,7 +82,7 @@ class WebhookBotISpec private val testChatJoinRequest = ChatJoinRequest( - Chat(0, `type` = ""), + testChat, testUser, 0L, 0 @@ -223,6 +230,26 @@ class WebhookBotISpec verifyResult(testUpdate.copy(editedChannelPost = testMessage.some), "onEditedChannelPostReply") } + "message reaction" in { + mockServerClient + .when(sendMessageRequest("onMessageReaction")) + .respond(sendMessageResponse) + verifyResult( + testUpdate.copy(messageReaction = MessageReactionUpdated(testChat, 0, 0).some), + "onMessageReactionReply" + ) + } + + "message reaction count" in { + mockServerClient + .when(sendMessageRequest("onMessageReactionCount")) + .respond(sendMessageResponse) + verifyResult( + testUpdate.copy(messageReactionCount = MessageReactionCountUpdated(testChat, 0, 0).some), + "onMessageReactionCountReply" + ) + } + "inline query" in { mockServerClient .when(sendMessageRequest("onInlineQuery")) @@ -320,6 +347,30 @@ class WebhookBotISpec .respond(sendMessageResponse) verifyResult(testUpdate.copy(chatJoinRequest = testChatJoinRequest.some), "onChatJoinRequestReply") } + + "chat boost" in { + mockServerClient + .when(sendMessageRequest("onChatBoost")) + .respond(sendMessageResponse) + verifyResult( + testUpdate.copy(chatBoost = + ChatBoostUpdated(testChat, ChatBoost("", 0, 0, ChatBoostSourcePremium("", testUser))).some + ), + "onChatBoostReply" + ) + } + + "removed chat boost" in { + mockServerClient + .when(sendMessageRequest("onRemovedChatBoost")) + .respond(sendMessageResponse) + verifyResult( + testUpdate.copy(removedChatBoost = + ChatBoostRemoved(testChat, "", 0, ChatBoostSourcePremium("", testUser)).some + ), + "onRemovedChatBoostReply" + ) + } } override protected def afterAll(): Unit = { diff --git a/telegramium-high/src/test/scala/telegramium/bots/high/messageentities/MessageEntitiesSpec.scala b/telegramium-high/src/test/scala/telegramium/bots/high/messageentities/MessageEntitiesSpec.scala index 20a39ed3..8b4de158 100644 --- a/telegramium-high/src/test/scala/telegramium/bots/high/messageentities/MessageEntitiesSpec.scala +++ b/telegramium-high/src/test/scala/telegramium/bots/high/messageentities/MessageEntitiesSpec.scala @@ -71,6 +71,12 @@ class MessageEntitiesSpec extends AnyFlatSpec with Matchers { entities.toTelegramEntities() shouldBe List(EmailMessageEntity(0, 19)) } + it should "add blockquote correctly" in { + val entities = MessageEntities().blockquote("test") + entities.toPlainText() shouldBe "test" + entities.toTelegramEntities() shouldBe List(BlockquoteMessageEntity(0, 4)) + } + it should "add pre correctly" in { val entities = MessageEntities().pre("test", Some("scala")) entities.toPlainText() shouldBe "test" @@ -139,6 +145,8 @@ class MessageEntitiesSpec extends AnyFlatSpec with Matchers { .plain(" ") .email("example@example.com") .plain(" ") + .blockquote("blockquote") + .plain(" ") .pre("pre", Some("scala")) .plain(" ") .italic("italic") @@ -159,25 +167,26 @@ class MessageEntitiesSpec extends AnyFlatSpec with Matchers { .lineBreak() entities - .toPlainText() shouldBe "bold @mention $USD code /command example@example.com pre italic strikethrough underline #hashtag textMention textLink https://example.com +12065550100\n" + .toPlainText() shouldBe "bold @mention $USD code /command example@example.com blockquote pre italic strikethrough underline #hashtag textMention textLink https://example.com +12065550100\n" val messageEntities = entities.toTelegramEntities() - messageEntities.size should be(15) + messageEntities.size should be(16) messageEntities.head should be(BoldMessageEntity(0, 4)) messageEntities(1) should be(MentionMessageEntity(5, 8)) messageEntities(2) should be(CashtagMessageEntity(14, 4)) messageEntities(3) should be(CodeMessageEntity(19, 4)) messageEntities(4) should be(BotCommandMessageEntity(24, 8)) messageEntities(5) should be(EmailMessageEntity(33, 19)) - messageEntities(6) should be(PreMessageEntity(53, 3, Some("scala"))) - messageEntities(7) should be(ItalicMessageEntity(57, 6)) - messageEntities(8) should be(StrikethroughMessageEntity(64, 13)) - messageEntities(9) should be(UnderlineMessageEntity(78, 9)) - messageEntities(10) should be(HashtagMessageEntity(88, 8)) - messageEntities(11) should be(TextMentionMessageEntity(97, 11, user)) - messageEntities(12) should be(TextLinkMessageEntity(109, 8, "https://example.com")) - messageEntities(13) should be(UrlMessageEntity(118, 19)) - messageEntities.last should be(PhoneNumberMessageEntity(138, 12)) + messageEntities(6) should be(BlockquoteMessageEntity(53, 10)) + messageEntities(7) should be(PreMessageEntity(64, 3, Some("scala"))) + messageEntities(8) should be(ItalicMessageEntity(68, 6)) + messageEntities(9) should be(StrikethroughMessageEntity(75, 13)) + messageEntities(10) should be(UnderlineMessageEntity(89, 9)) + messageEntities(11) should be(HashtagMessageEntity(99, 8)) + messageEntities(12) should be(TextMentionMessageEntity(108, 11, user)) + messageEntities(13) should be(TextLinkMessageEntity(120, 8, "https://example.com")) + messageEntities(14) should be(UrlMessageEntity(129, 19)) + messageEntities.last should be(PhoneNumberMessageEntity(149, 12)) } }