diff --git a/README.md b/README.md index bce4ff4..f62a250 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -| WARNING: Be careful when installing RxTelegram.Bot. DO NOT INSTALL RxTelegram.Bot2. Since RxTelegram.Bot2 does not send your Requests to the official Telegram API and can read your entire traffic. | -| --- | # RxTelegram.Bot [![NuGet](http://img.shields.io/nuget/v/RxTelegram.Bot.svg)](https://www.nuget.org/packages/RxTelegram.Bot) @@ -7,7 +5,7 @@ [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=RxTelegram_RxTelegram.Bot&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=RxTelegram_RxTelegram.Bot) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=RxTelegram_RxTelegram.Bot&metric=coverage)](https://sonarcloud.io/summary/new_code?id=RxTelegram_RxTelegram.Bot) -RxTelegram.Bot supports Telegram Bot API 7.2 (as at March 31, 2024). +RxTelegram.Bot supports Telegram Bot API 7.3 (as at May 6, 2024). This is a reactive designed .NET Library for the Telegram Bot API. It works with the official [Reactive Extentions](https://github.com/dotnet/reactive). diff --git a/src/RxTelegram.Bot/ITelegramBot.cs b/src/RxTelegram.Bot/ITelegramBot.cs index 3278cae..8d82b88 100644 --- a/src/RxTelegram.Bot/ITelegramBot.cs +++ b/src/RxTelegram.Bot/ITelegramBot.cs @@ -185,7 +185,9 @@ public interface ITelegramBot /// Details for the live location to edit. /// Propagates notification that operations should be canceled. /// On success, if the edited message was sent by the bot, the edited is returned, otherwise True is returned. - Task EditMessageLiveLocation(EditMessageLiveLocation editMessageLiveLocation, CancellationToken cancellationToken = default); + Task EditMessageLiveLocation( + EditMessageLiveLocation editMessageLiveLocation, + CancellationToken cancellationToken = default); /// /// Use this method to get up to date information about the chat (current name of the user for one-on-one conversations, @@ -194,7 +196,7 @@ public interface ITelegramBot /// ChatId for the request. /// Propagates notification that operations should be canceled. /// Returns a object on success. - Task GetChat(GetChat getChat, CancellationToken cancellationToken = default); + Task GetChat(GetChat getChat, CancellationToken cancellationToken = default); /// /// Use this method to get information about a member of a chat. @@ -218,7 +220,9 @@ public interface ITelegramBot /// Filter for the requested username. /// Propagates notification that operations should be canceled. /// Returns a object. - Task GetUserProfilePhotos(GetUserProfilePhotos getUserProfilePhotos, CancellationToken cancellationToken = default); + Task GetUserProfilePhotos( + GetUserProfilePhotos getUserProfilePhotos, + CancellationToken cancellationToken = default); /// /// Use this method to get a list of administrators in a chat. @@ -376,7 +380,9 @@ Task> GetChatAdministrators( /// Sets the thumbnail picture for the sticker set. /// Propagates notification that operations should be canceled. /// Returns True on success. - Task SetStickerSetThumbnail(SetStickerSetThumbnail setStickerSetThumbnail, CancellationToken cancellationToken = default); + Task SetStickerSetThumbnail( + SetStickerSetThumbnail setStickerSetThumbnail, + CancellationToken cancellationToken = default); /// /// Use this method to send static .WEBP or animated .TGS stickers. @@ -461,7 +467,9 @@ Task> GetChatAdministrators( /// Details for the sticker that should be repositioned in the sticker set. /// Propagates notification that operations should be canceled. /// Returns True on success. - Task SetStickerPositionInSet(SetStickerPositionInSet setStickerPositionInSet, CancellationToken cancellationToken = default); + Task SetStickerPositionInSet( + SetStickerPositionInSet setStickerPositionInSet, + CancellationToken cancellationToken = default); /// /// Use this method when you need to tell the user that something is happening on the bot's side. @@ -538,7 +546,9 @@ Task SetChatAdministratorCustomTitle( /// Will return the score of the specified user and several of their neighbors in a game. /// On success, returns an Array of GameHighScore objects. /// - Task> GetGameHighScores(GetGameHighScores getGameHighScores, CancellationToken cancellationToken = default); + Task> GetGameHighScores( + GetGameHighScores getGameHighScores, + CancellationToken cancellationToken = default); /// /// Use this method to stop updating a live location message before live_period expires. @@ -546,7 +556,9 @@ Task SetChatAdministratorCustomTitle( /// MessageId of the liveLocation that should be stopped. /// Propagates notification that operations should be canceled. /// On success, if the message was sent by the bot, the sent Message is returned, otherwise True is returned. - Task StopMessageLiveLocation(StopMessageLiveLocation stopMessageLiveLocation, CancellationToken cancellationToken = default); + Task StopMessageLiveLocation( + StopMessageLiveLocation stopMessageLiveLocation, + CancellationToken cancellationToken = default); Task StopMessageLiveLocationInlineMessage( StopMessageLiveLocation stopMessageLiveLocation, @@ -618,7 +630,9 @@ Task StopMessageLiveLocationInlineMessage( /// New reply markup for the message. /// Propagates notification that operations should be canceled. /// On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. - Task EditMessageReplyMarkup(EditMessageReplyMarkup editMessageReplyMarkup, CancellationToken cancellationToken = default); + Task EditMessageReplyMarkup( + EditMessageReplyMarkup editMessageReplyMarkup, + CancellationToken cancellationToken = default); /// /// Use this method to send invoices. @@ -645,7 +659,9 @@ Task StopMessageLiveLocationInlineMessage( /// Answer for the preCheckoutQuery /// Propagates notification that operations should be canceled. /// On success, True is returned. - Task AnswerPreCheckoutQuery(AnswerPreCheckoutQuery answerPreCheckoutQuery, CancellationToken cancellationToken = default); + Task AnswerPreCheckoutQuery( + AnswerPreCheckoutQuery answerPreCheckoutQuery, + CancellationToken cancellationToken = default); /// /// Informs a user that some of the Telegram Passport elements they provided contains errors. @@ -765,7 +781,9 @@ Task StopMessageLiveLocationInlineMessage( /// Details for the chat invite link to create. /// Propagates notification that operations should be canceled. /// Returns the new invite link as . - Task CreateChatInviteLink(CreateChatInviteLink createChatInviteLink, CancellationToken cancellationToken = default); + Task CreateChatInviteLink( + CreateChatInviteLink createChatInviteLink, + CancellationToken cancellationToken = default); /// /// Use this method to edit a non-primary invite link created by the bot. @@ -784,7 +802,9 @@ Task StopMessageLiveLocationInlineMessage( /// Details for the invite link to revoke. /// Propagates notification that operations should be canceled. /// Returns the revoked invite link as object. - Task RevokeChatInviteLink(RevokeChatInviteLink revokeChatInviteLink, CancellationToken cancellationToken = default); + Task RevokeChatInviteLink( + RevokeChatInviteLink revokeChatInviteLink, + CancellationToken cancellationToken = default); /// /// Use this method to approve a chat join request. @@ -793,7 +813,9 @@ Task StopMessageLiveLocationInlineMessage( /// Join request to approve /// Propagates notification that operations should be canceled. /// Returns True on success. - Task ApproveChatJoinRequest(ApproveChatJoinRequest approveChatJoinRequest, CancellationToken cancellationToken = default); + Task ApproveChatJoinRequest( + ApproveChatJoinRequest approveChatJoinRequest, + CancellationToken cancellationToken = default); /// /// Use this method to decline a chat join request. @@ -802,7 +824,9 @@ Task StopMessageLiveLocationInlineMessage( /// Join request to decline /// Propagates notification that operations should be canceled. /// Returns True on success. - Task DeclineChatJoinRequest(DeclineChatJoinRequest declineChatJoinRequest, CancellationToken cancellationToken = default); + Task DeclineChatJoinRequest( + DeclineChatJoinRequest declineChatJoinRequest, + CancellationToken cancellationToken = default); /// /// Use this method to ban a channel chat in a supergroup or a channel. @@ -876,7 +900,9 @@ Task GetMyDefaultAdministratorRights( /// Sticker ids to get /// Propagates notification that operations should be canceled. /// Returns an Array of Sticker objects. - Task GetCustomEmojiStickers(GetCustomEmojiStickers getCustomEmojiStickers, CancellationToken cancellationToken = default); + Task GetCustomEmojiStickers( + GetCustomEmojiStickers getCustomEmojiStickers, + CancellationToken cancellationToken = default); /// /// Use this method to create a topic in a forum supergroup chat. @@ -960,7 +986,9 @@ Task UnpinAllForumTopicMessages( /// General Forum Topic to close /// Propagates notification that operations should be canceled. /// Returns True on success. - Task CloseGeneralForumTopic(CloseGeneralForumTopic closeGeneralForumTopic, CancellationToken cancellationToken = default); + Task CloseGeneralForumTopic( + CloseGeneralForumTopic closeGeneralForumTopic, + CancellationToken cancellationToken = default); /// /// Use this method to reopen a closed 'General' topic in a forum supergroup chat. @@ -970,7 +998,9 @@ Task UnpinAllForumTopicMessages( /// General forum topic to reopen /// Propagates notification that operations should be canceled. /// Returns True on success. - Task ReopenGeneralForumTopic(ReopenGeneralForumTopic reopenGeneralForumTopic, CancellationToken cancellationToken = default); + Task ReopenGeneralForumTopic( + ReopenGeneralForumTopic reopenGeneralForumTopic, + CancellationToken cancellationToken = default); /// /// Use this method to hide the 'General' topic in a forum supergroup chat. @@ -989,7 +1019,9 @@ Task UnpinAllForumTopicMessages( /// General Forum topic to unhide /// Propagates notification that operations should be canceled. /// Returns True on success. - Task UnhideGeneralForumTopic(UnhideGeneralForumTopic unhideGeneralForumTopic, CancellationToken cancellationToken = default); + Task UnhideGeneralForumTopic( + UnhideGeneralForumTopic unhideGeneralForumTopic, + CancellationToken cancellationToken = default); /// /// Use this method to change the bot's description, which is shown in the chat with the bot if the chat is empty. @@ -1077,7 +1109,9 @@ Task SetCustomEmojiStickerSetThumbnail( /// Mask position to set for a sticker /// Propagates notification that operations should be canceled. /// Returns True on success. - Task SetStickerMaskPosition(SetStickerMaskPosition setStickerMaskPosition, CancellationToken cancellationToken = default); + Task SetStickerMaskPosition( + SetStickerMaskPosition setStickerMaskPosition, + CancellationToken cancellationToken = default); /// /// Use this method to change the bot's name. @@ -1131,8 +1165,8 @@ Task UnpinAllGeneralForumTopicMessages( /// /// MessageIds to forward /// Propagates notification that operations should be canceled. - /// Returns True on success. - Task ForwardMessages(ForwardMessages forwardMessages, CancellationToken cancellationToken = default); + /// On success, an array of with the send messages is returned. + Task ForwardMessages(ForwardMessages forwardMessages, CancellationToken cancellationToken = default); /// /// Use this method to get the list of boosts added to a chat by a user. Requires administrator rights in the chat. @@ -1161,4 +1195,16 @@ Task GetBusinessConnection( /// Propagates notification that operations should be canceled. /// Returns True on success. Task ReplaceStickerInSet(ReplaceStickerInSet replaceStickerInSet, CancellationToken cancellationToken = default); + + /// + /// 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. + /// + /// Information about the messages to copy + /// Propagates notification that operations should be canceled. + /// Returns an array of on success. + Task CopyMessages(CopyMessages copyMessages, CancellationToken cancellationToken = default); } diff --git a/src/RxTelegram.Bot/Interface/BaseTypes/Chat.cs b/src/RxTelegram.Bot/Interface/BaseTypes/Chat.cs index 81e7add..d5d621c 100644 --- a/src/RxTelegram.Bot/Interface/BaseTypes/Chat.cs +++ b/src/RxTelegram.Bot/Interface/BaseTypes/Chat.cs @@ -14,7 +14,9 @@ namespace RxTelegram.Bot.Interface.BaseTypes; public class Chat { /// - /// Unique identifier for this chat, not exceeding 1e13 by absolute value + /// Unique identifier for this chat. + /// 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 signed 64-bit integer or double-precision float type are safe for storing this identifier. /// public long Id { get; set; } @@ -24,12 +26,12 @@ public class Chat public ChatType Type { get; set; } /// - /// Optional. Title, for channels and group chats + /// Optional. Title, for supergroups, channels and group chats /// public string Title { get; set; } /// - /// Optional. Username, for private chats and channels if available + /// Optional. Username, for private chats, supergroups and channels if available /// public string Username { get; set; } @@ -46,220 +48,5 @@ public class Chat /// /// Optional. True, if the supergroup chat is a forum (has topics enabled) /// - public bool? IsForum { get; set; } - - /// - /// Optional. True if a group has 'All Members Are Admins' enabled. - /// - [Obsolete("Use Permissions field instead")] - public bool AllMembersAreAdministrators { get; set; } - - /// - /// Optional. Chat photo. Returned only in getChat. - /// - public ChatPhoto Photo { get; set; } - - /// - /// Optional. If non-empty, the list of all active chat usernames; for private chats, supergroups and channels. - /// Returned only in . - /// - public List ActiveUsernames { get; set; } - - /// - /// Optional. For private chats, the date of birth of the user. - /// Returned only in . - /// - public Birthdate Birthdate { get; set; } - - /// - /// Optional. For private chats with business accounts, the intro of the business. - /// Returned only in . - /// - public BusinessIntro BusinessIntro { get; set; } - - /// - /// Optional. For private chats with business accounts, the location of the business. - /// Returned only in . - /// - public BusinessLocation BusinessLocation { get; set; } - - /// - /// Optional. For private chats with business accounts, the opening hours of the business. - /// Returned only in . - /// - public BusinessOpeningHours BusinessOpeningHours { get; set; } - - /// - /// Optional. For private chats, the personal channel of the user. - /// Returned only in . - /// - public Chat PersonalChat { get; set; } - - /// - /// Optional. List of available reactions allowed in the chat. If omitted, then all emoji reactions are allowed. - /// Returned only in . - /// - public List AvailableReactions { get; set; } - - /// - /// 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 . - /// Always returned in . - /// - public long? AccentColorId { get; set; } - - /// - /// Optional. Custom emoji identifier of emoji chosen by the chat for the reply header and link preview background. - /// Returned only in . - /// - public string BackgroundCustomEmojiId { get; set; } - - /// - /// Optional. Identifier of the accent color for the chat's profile background. See profile accent colors for more details. - /// Returned only in . - /// - public long? ProfileAccentColorId { get; set; } - - /// - /// Optional. Custom emoji identifier of the emoji chosen by the chat for its profile background. - /// Returned only in . - /// - public string ProfileBackgroundCustomEmojiId { get; set; } - - /// - /// Optional. Custom emoji identifier of emoji status of the other party in a private chat. - /// Returned only in . - /// - public string EmojiStatusCustomEmojiId { get; set; } - - /// - /// Optional. Expiration date of the emoji status of the other party in a private chat, if any. - /// Returned only in . - /// - public long EmojiStatusExpirationDate { get; set; } - - /// - /// Bio of the other party in a private chat. Returned only in . - /// - public string Bio { get; set; } - - /// - /// Optional. True, if privacy settings of the other party in the private chat allows to - /// use tg://user?id=[user_id] links only in chats with the user. Returned only in getChat. - /// - public bool? HasPrivateForwards { get; set; } - - /// - /// Optional. True, if the privacy settings of the other party restrict sending voice and - /// video note messages in the private chat. Returned only in getChat. - /// - public bool? HasRestrictedVoiceAndVideoMessages { get; set; } - - /// - /// Optional. True, if users need to join the supergroup before they can send messages. - /// Returned only in getChat. - /// - public bool? JoinToSendMessages { get; set; } - - /// - /// Optional. True, if all users directly joining the supergroup need to be approved by supergroup administrators. - /// Returned only in getChat. - /// - public bool? JoinByRequest { get; set; } - - /// - /// Optional. Description, for supergroups and channel chats. Returned only in getChat. - /// - public string Description { get; set; } - - /// - /// Optional. Chat invite link, for supergroups and channel chats. Returned only in getChat. - /// - public string InviteLink { get; set; } - - /// - /// Optional. Pinned message, for supergroups. Returned only in getChat. - /// - public Message PinnedMessage { get; set; } - - /// - /// Optional. Pinned message, for groups, supergroups and channels. Returned only in getChat. - /// - public ChatPermissions Permissions { get; set; } - - /// - /// Optional. For supergroups, the minimum allowed delay between consecutive - /// messages sent by each unprivileged user. Returned only in getChat. - /// - public int? SlowModeDelay { get; set; } - - /// - /// Optional. For supergroups, the minimum number of boosts that a non-administrator user needs to add in order to ignore - /// slow mode and chat permissions. Returned only in . - /// - public int? UnrestrictBoostCount { get; set; } - - /// - /// Optional. The time after which all messages sent to the chat will be automatically deleted; in seconds. - /// Returned only in getChat. - /// - public int? MessageAutoDeleteTime { get; set; } - - /// - /// Optional. True, if aggressive anti-spam checks are enabled in the supergroup. - /// The field is only available to chat administrators. - /// Returned only in getChat. - /// - public bool? HasAggressiveAntiSpamEnabled { get; set; } - - /// - /// Optional. True, if non-administrators can only get the list of bots and administrators in the chat. - /// Returned only in getChat. - /// - public bool? HasHiddenMembers { get; set; } - - /// - /// Optional. True, if messages from the chat can't be forwarded to other chats. - /// Returned only in getChat. - /// - public bool? HasProtectedContent { get; set; } - - /// - /// Optional. True, if new chat members will have access to old messages; available only to chat administrators. - /// Returned only in . - /// - public bool? HasVisibleHistory { get; set; } - - /// - /// Optional. For supergroups, name of group sticker set. Returned only in getChat. - /// - public string StickerSetName { get; set; } - - /// - /// Optional. True, if the bot can change the group sticker set. - /// Returned only in . - /// - public bool? CanSetStickerSet { get; set; } - - /// - /// Optional. For supergroups, the name of the group's custom emoji sticker set. - /// Custom emoji from this set can be used by all users and bots in the group. - /// Returned only in . - /// - public string CustomEmojiStickerSetName { get; set; } - - /// - /// Unique identifier for the linked chat, i.e. the discussion group identifier for a channel and vice versa; - /// for supergroups and channel chats. This identifier may be greater than 32 bits and some programming languages - /// may have difficulty/silent defects in interpreting it. But it is smaller than 52 bits, so a signed 64 bit integer - /// or double-precision float type are safe for storing this identifier. - /// Returned only in . - /// - public long? LinkedChatId { get; set; } - - /// - /// For supergroups, the location to which the supergroup is connected. - /// Returned only in . - /// - public ChatLocation Location { get; set; } + public bool IsForum { get; set; } } diff --git a/src/RxTelegram.Bot/Interface/BaseTypes/ChatFullInfo.cs b/src/RxTelegram.Bot/Interface/BaseTypes/ChatFullInfo.cs new file mode 100644 index 0000000..0841cf3 --- /dev/null +++ b/src/RxTelegram.Bot/Interface/BaseTypes/ChatFullInfo.cs @@ -0,0 +1,261 @@ +using System.Collections.Generic; +using System.Threading; +using RxTelegram.Bot.Interface.BaseTypes.Enums; +using RxTelegram.Bot.Interface.BaseTypes.Requests.Chats; +using RxTelegram.Bot.Interface.Business; +using RxTelegram.Bot.Interface.Reaction.Enums; + +namespace RxTelegram.Bot.Interface.BaseTypes; + +public class ChatFullInfo +{ + /// + /// Unique identifier for this chat, not exceeding 1e13 by absolute value + /// + public long Id { get; set; } + + /// + /// Type of chat + /// + public ChatType Type { get; set; } + + /// + /// Optional. Title, for channels and group chats + /// + public string Title { get; set; } + + /// + /// Optional. Username, for private chats and channels if available + /// + public string Username { get; set; } + + /// + /// Optional. First name of the other party in a private chat + /// + public string FirstName { get; set; } + + /// + /// Optional. Last name of the other party in a private chat + /// + public string LastName { get; set; } + + /// + /// Optional. True, if the supergroup chat is a forum (has topics enabled) + /// + public bool? IsForum { get; set; } + + /// + /// 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. + /// + public long AccentColorId { get; set; } + + /// + /// The maximum number of reactions that can be set on a message in the chat + /// + public int MaxReactionCount { get; set; } + + /// + /// Optional. Chat photo. Returned only in getChat. + /// + public ChatPhoto Photo { get; set; } + + /// + /// Optional. If non-empty, the list of all active chat usernames; for private chats, supergroups and channels. + /// Returned only in . + /// + public List ActiveUsernames { get; set; } + + /// + /// Optional. For private chats, the date of birth of the user. + /// Returned only in . + /// + public Birthdate Birthdate { get; set; } + + /// + /// Optional. For private chats with business accounts, the intro of the business. + /// Returned only in . + /// + public BusinessIntro BusinessIntro { get; set; } + + /// + /// Optional. For private chats with business accounts, the location of the business. + /// Returned only in . + /// + public BusinessLocation BusinessLocation { get; set; } + + /// + /// Optional. For private chats with business accounts, the opening hours of the business. + /// Returned only in . + /// + public BusinessOpeningHours BusinessOpeningHours { get; set; } + + /// + /// Optional. For private chats, the personal channel of the user. + /// Returned only in . + /// + public Chat PersonalChat { get; set; } + + /// + /// Optional. List of available reactions allowed in the chat. If omitted, then all emoji reactions are allowed. + /// Returned only in . + /// + public List AvailableReactions { get; set; } + + /// + /// Optional. Custom emoji identifier of emoji chosen by the chat for the reply header and link preview background. + /// Returned only in . + /// + public string BackgroundCustomEmojiId { get; set; } + + + + /// + /// Optional. Identifier of the accent color for the chat's profile background. See profile accent colors for more details. + /// Returned only in . + /// + public long? ProfileAccentColorId { get; set; } + + /// + /// Optional. Custom emoji identifier of the emoji chosen by the chat for its profile background. + /// Returned only in . + /// + public string ProfileBackgroundCustomEmojiId { get; set; } + + /// + /// Optional. Custom emoji identifier of emoji status of the other party in a private chat. + /// Returned only in . + /// + public string EmojiStatusCustomEmojiId { get; set; } + + /// + /// Optional. Expiration date of the emoji status of the other party in a private chat, if any. + /// Returned only in . + /// + public long EmojiStatusExpirationDate { get; set; } + + /// + /// Bio of the other party in a private chat. Returned only in . + /// + public string Bio { get; set; } + + /// + /// Optional. True, if privacy settings of the other party in the private chat allows to + /// use tg://user?id=[user_id] links only in chats with the user. Returned only in getChat. + /// + public bool? HasPrivateForwards { get; set; } + + /// + /// Optional. True, if the privacy settings of the other party restrict sending voice and + /// video note messages in the private chat. Returned only in getChat. + /// + public bool? HasRestrictedVoiceAndVideoMessages { get; set; } + + /// + /// Optional. True, if users need to join the supergroup before they can send messages. + /// Returned only in getChat. + /// + public bool? JoinToSendMessages { get; set; } + + /// + /// Optional. True, if all users directly joining the supergroup need to be approved by supergroup administrators. + /// Returned only in getChat. + /// + public bool? JoinByRequest { get; set; } + + /// + /// Optional. Description, for supergroups and channel chats. Returned only in getChat. + /// + public string Description { get; set; } + + /// + /// Optional. Chat invite link, for supergroups and channel chats. Returned only in getChat. + /// + public string InviteLink { get; set; } + + /// + /// Optional. Pinned message, for supergroups. Returned only in getChat. + /// + public Message PinnedMessage { get; set; } + + /// + /// Optional. Pinned message, for groups, supergroups and channels. Returned only in getChat. + /// + public ChatPermissions Permissions { get; set; } + + /// + /// Optional. For supergroups, the minimum allowed delay between consecutive + /// messages sent by each unprivileged user. Returned only in getChat. + /// + public int? SlowModeDelay { get; set; } + + /// + /// Optional. For supergroups, the minimum number of boosts that a non-administrator user needs to add in order to ignore + /// slow mode and chat permissions. Returned only in . + /// + public int? UnrestrictBoostCount { get; set; } + + /// + /// Optional. The time after which all messages sent to the chat will be automatically deleted; in seconds. + /// Returned only in getChat. + /// + public int? MessageAutoDeleteTime { get; set; } + + /// + /// Optional. True, if aggressive anti-spam checks are enabled in the supergroup. + /// The field is only available to chat administrators. + /// Returned only in getChat. + /// + public bool? HasAggressiveAntiSpamEnabled { get; set; } + + /// + /// Optional. True, if non-administrators can only get the list of bots and administrators in the chat. + /// Returned only in getChat. + /// + public bool? HasHiddenMembers { get; set; } + + /// + /// Optional. True, if messages from the chat can't be forwarded to other chats. + /// Returned only in getChat. + /// + public bool? HasProtectedContent { get; set; } + + /// + /// Optional. True, if new chat members will have access to old messages; available only to chat administrators. + /// Returned only in . + /// + public bool? HasVisibleHistory { get; set; } + + /// + /// Optional. For supergroups, name of group sticker set. Returned only in getChat. + /// + public string StickerSetName { get; set; } + + /// + /// Optional. True, if the bot can change the group sticker set. + /// Returned only in . + /// + public bool? CanSetStickerSet { get; set; } + + /// + /// Optional. For supergroups, the name of the group's custom emoji sticker set. + /// Custom emoji from this set can be used by all users and bots in the group. + /// Returned only in . + /// + public string CustomEmojiStickerSetName { get; set; } + + /// + /// Unique identifier for the linked chat, i.e. the discussion group identifier for a channel and vice versa; + /// for supergroups and channel chats. This identifier may be greater than 32 bits and some programming languages + /// may have difficulty/silent defects in interpreting it. But it is smaller than 52 bits, so a signed 64 bit integer + /// or double-precision float type are safe for storing this identifier. + /// Returned only in . + /// + public long? LinkedChatId { get; set; } + + /// + /// For supergroups, the location to which the supergroup is connected. + /// Returned only in . + /// + public ChatLocation Location { get; set; } +} diff --git a/src/RxTelegram.Bot/Interface/BaseTypes/ChatMemberUpdated.cs b/src/RxTelegram.Bot/Interface/BaseTypes/ChatMemberUpdated.cs index 79f6d3e..deb8427 100644 --- a/src/RxTelegram.Bot/Interface/BaseTypes/ChatMemberUpdated.cs +++ b/src/RxTelegram.Bot/Interface/BaseTypes/ChatMemberUpdated.cs @@ -37,6 +37,12 @@ public class ChatMemberUpdated /// public ChatInviteLink InviteLink { get; set; } + /// + /// Optional. + /// True, if the user joined the chat after sending a direct join request without using an invite link and being approved by an administrator + /// + public bool ViaJoinRequest { get; set; } + /// /// Optional. True, if the user joined the chat via a chat folder invite link /// diff --git a/src/RxTelegram.Bot/Interface/BaseTypes/Enums/ParseMode.cs b/src/RxTelegram.Bot/Interface/BaseTypes/Enums/ParseMode.cs index f5adc2b..33e4a69 100644 --- a/src/RxTelegram.Bot/Interface/BaseTypes/Enums/ParseMode.cs +++ b/src/RxTelegram.Bot/Interface/BaseTypes/Enums/ParseMode.cs @@ -2,7 +2,9 @@ namespace RxTelegram.Bot.Interface.BaseTypes.Enums; public enum ParseMode { + MarkdownV2, + Markdown, HTML -} \ No newline at end of file +} diff --git a/src/RxTelegram.Bot/Interface/BaseTypes/InputPollOption.cs b/src/RxTelegram.Bot/Interface/BaseTypes/InputPollOption.cs new file mode 100644 index 0000000..84eecf1 --- /dev/null +++ b/src/RxTelegram.Bot/Interface/BaseTypes/InputPollOption.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; + +namespace RxTelegram.Bot.Interface.BaseTypes; + +/// +/// This object contains information about one answer option in a poll to send. +/// +public class InputPollOption +{ + /// + /// Option text, 1-100 characters + /// + public string Text { get; set; } + + /// + /// Optional. Mode for parsing entities in the text. See formatting options for more details. + /// Currently, only custom emoji entities are allowed + /// + public string TextParseMode { get; set; } + + /// + /// Optional. A JSON-serialized list of special entities that appear in the poll option text. + /// It can be specified instead of + /// + public List TextEntities { get; set; } +} diff --git a/src/RxTelegram.Bot/Interface/BaseTypes/Message.cs b/src/RxTelegram.Bot/Interface/BaseTypes/Message.cs index 915a570..40125d8 100644 --- a/src/RxTelegram.Bot/Interface/BaseTypes/Message.cs +++ b/src/RxTelegram.Bot/Interface/BaseTypes/Message.cs @@ -45,6 +45,11 @@ public class Message /// public ChatBoostAdded BoostAdded { get; set; } + /// + /// Optional. Service message: chat background set + /// + public ChatBackground.ChatBackground ChatBackgroundSet { get; set; } + /// /// Optional. The bot that actually sent the message on behalf of the business account. /// Available only for outgoing messages sent on behalf of the connected business account. diff --git a/src/RxTelegram.Bot/Interface/BaseTypes/Poll.cs b/src/RxTelegram.Bot/Interface/BaseTypes/Poll.cs index 7581235..10941a5 100644 --- a/src/RxTelegram.Bot/Interface/BaseTypes/Poll.cs +++ b/src/RxTelegram.Bot/Interface/BaseTypes/Poll.cs @@ -18,6 +18,11 @@ public class Poll /// public string Question { get; set; } + /// + /// Optional. Special entities that appear in the question. Currently, only custom emoji entities are allowed in poll questions + /// + public List QuestionEntities { get; set; } + /// /// List of poll options /// diff --git a/src/RxTelegram.Bot/Interface/BaseTypes/PollOption.cs b/src/RxTelegram.Bot/Interface/BaseTypes/PollOption.cs index 0dc189d..702f9ce 100644 --- a/src/RxTelegram.Bot/Interface/BaseTypes/PollOption.cs +++ b/src/RxTelegram.Bot/Interface/BaseTypes/PollOption.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; + namespace RxTelegram.Bot.Interface.BaseTypes; /// @@ -10,6 +12,11 @@ public class PollOption /// public string Text { get; set; } + /// + /// Optional. Special entities that appear in the option text. Currently, only custom emoji entities are allowed in poll option texts + /// + public List TextEntities { get; set; } + /// /// Number of users that voted for this option /// diff --git a/src/RxTelegram.Bot/Interface/BaseTypes/Requests/Attachments/EditMessageLiveLocation.cs b/src/RxTelegram.Bot/Interface/BaseTypes/Requests/Attachments/EditMessageLiveLocation.cs index 01accdf..b4c0840 100644 --- a/src/RxTelegram.Bot/Interface/BaseTypes/Requests/Attachments/EditMessageLiveLocation.cs +++ b/src/RxTelegram.Bot/Interface/BaseTypes/Requests/Attachments/EditMessageLiveLocation.cs @@ -32,6 +32,14 @@ public class EditMessageLiveLocation : BaseRequest /// public double Longitude { get; set; } + /// + /// New period in seconds during which the location can be updated, starting from the message send date. + /// If 0x7FFFFFFF is specified, then the location can be updated forever. + /// Otherwise, the new value must not exceed the current live_period by more than a day, and the live location expiration date must remain within the next 90 days. + /// If not specified, then live_period remains unchanged + /// + public int LivePeriod { get; set; } = 0x7FFFFFFF; + /// /// The radius of uncertainty for the location, measured in meters; 0-1500 /// diff --git a/src/RxTelegram.Bot/Interface/BaseTypes/Requests/Attachments/SendPoll.cs b/src/RxTelegram.Bot/Interface/BaseTypes/Requests/Attachments/SendPoll.cs index 9fed1e1..c823ddf 100644 --- a/src/RxTelegram.Bot/Interface/BaseTypes/Requests/Attachments/SendPoll.cs +++ b/src/RxTelegram.Bot/Interface/BaseTypes/Requests/Attachments/SendPoll.cs @@ -28,11 +28,22 @@ public class SendPoll : BaseRequest, IProtectContent /// public string Question { get; set; } + /// + /// Mode for parsing entities in the question. See formatting options for more details. + /// urrently, only custom emoji entities are allowed + /// + public string QuestionParseMode { get; set; } + + /// + /// A JSON-serialized list of special entities that appear in the poll question. It can be specified instead of question_parse_mode + /// + public IEnumerable QuestionEntities { get; set; } + /// /// Required /// A JSON-serialized list of answer options, 2-10 strings 1-100 characters each /// - public IEnumerable Options { get; set; } + public IEnumerable Options { get; set; } /// /// Optional diff --git a/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundFill.cs b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundFill.cs new file mode 100644 index 0000000..8da244d --- /dev/null +++ b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundFill.cs @@ -0,0 +1,9 @@ +using RxTelegram.Bot.Interface.ChatBackground.Enums; +using RxTelegram.Bot.Utils.MultiType; + +namespace RxTelegram.Bot.Interface.ChatBackground; + +public abstract class BackgroundFill : IMultiTypeClassByType +{ + public abstract BackgroundFillTypes Type { get; set; } +} diff --git a/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundFillFreeformGradient.cs b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundFillFreeformGradient.cs new file mode 100644 index 0000000..0576879 --- /dev/null +++ b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundFillFreeformGradient.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using RxTelegram.Bot.Interface.ChatBackground.Enums; + +namespace RxTelegram.Bot.Interface.ChatBackground; + +/// +/// The background is a freeform gradient that rotates after every message in the chat. +/// +public class BackgroundFillFreeformGradient : BackgroundFill +{ + /// + /// Type of the background fill, always “freeform_gradient” + /// + public override BackgroundFillTypes Type { get; set; } = BackgroundFillTypes.FreeformGradient; + + /// + /// A list of the 3 or 4 base colors that are used to generate the freeform gradient in the RGB24 format + /// + public List Colors { get; set; } +} diff --git a/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundFillGradient.cs b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundFillGradient.cs new file mode 100644 index 0000000..67fb7fe --- /dev/null +++ b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundFillGradient.cs @@ -0,0 +1,29 @@ +using RxTelegram.Bot.Interface.ChatBackground.Enums; + +namespace RxTelegram.Bot.Interface.ChatBackground; + +/// +/// The background is a gradient fill. +/// +public class BackgroundFillGradient : BackgroundFill +{ + /// + /// Type of the background fill, always “gradient” + /// + public override BackgroundFillTypes Type { get; set; } = BackgroundFillTypes.Gradient; + + /// + /// Top color of the gradient in the RGB24 format + /// + public int TopColor { get; set; } + + /// + /// Bottom color of the gradient in the RGB24 format + /// + public int BottomColor { get; set; } + + /// + /// Clockwise rotation angle of the background fill in degrees; 0-359 + /// + public int RotationAngle { get; set; } +} diff --git a/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundFillSolid.cs b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundFillSolid.cs new file mode 100644 index 0000000..aa8a1c6 --- /dev/null +++ b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundFillSolid.cs @@ -0,0 +1,19 @@ +using RxTelegram.Bot.Interface.ChatBackground.Enums; + +namespace RxTelegram.Bot.Interface.ChatBackground; + +/// +/// The background is filled using the selected color. +/// +public class BackgroundFillSolid : BackgroundFill +{ + /// + /// Type of the background fill, always “solid” + /// + public override BackgroundFillTypes Type { get; set; } = BackgroundFillTypes.Solid; + + /// + /// The color of the background fill in the RGB24 format + /// + public long Color { get; set; } +} diff --git a/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundType.cs b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundType.cs new file mode 100644 index 0000000..64eeb5a --- /dev/null +++ b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundType.cs @@ -0,0 +1,9 @@ +using RxTelegram.Bot.Interface.ChatBackground.Enums; +using RxTelegram.Bot.Utils.MultiType; + +namespace RxTelegram.Bot.Interface.ChatBackground; + +public abstract class BackgroundType : IMultiTypeClassByType +{ + public abstract BackgroundTypes Type { get; set; } +} diff --git a/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundTypeChatTheme.cs b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundTypeChatTheme.cs new file mode 100644 index 0000000..07cb9f0 --- /dev/null +++ b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundTypeChatTheme.cs @@ -0,0 +1,19 @@ +using RxTelegram.Bot.Interface.ChatBackground.Enums; + +namespace RxTelegram.Bot.Interface.ChatBackground; + +/// +/// The background is taken directly from a built-in chat theme. +/// +public class BackgroundTypeChatTheme : BackgroundType +{ + /// + /// Type of the background, always “chat_theme” + /// + public override BackgroundTypes Type { get; set; } = BackgroundTypes.ChatTheme; + + /// + /// Name of the chat theme, which is usually an emoji + /// + public string ThemeName { get; set; } +} diff --git a/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundTypeFill.cs b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundTypeFill.cs new file mode 100644 index 0000000..23e23ec --- /dev/null +++ b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundTypeFill.cs @@ -0,0 +1,24 @@ +using RxTelegram.Bot.Interface.ChatBackground.Enums; + +namespace RxTelegram.Bot.Interface.ChatBackground; + +/// +/// The background is automatically filled based on the selected colors. +/// +public class BackgroundTypeFill : BackgroundType +{ + /// + /// Type of the background, always “fill” + /// + public override BackgroundTypes Type { get; set; } = BackgroundTypes.Fill; + + /// + /// The background fill + /// + public BackgroundFill Fill { get; set; } + + /// + /// Dimming of the background in dark themes, as a percentage; 0-100 + /// + public int DarkThemeDimming { get; set; } +} diff --git a/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundTypePattern.cs b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundTypePattern.cs new file mode 100644 index 0000000..54cac69 --- /dev/null +++ b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundTypePattern.cs @@ -0,0 +1,40 @@ +using RxTelegram.Bot.Interface.BaseTypes; +using RxTelegram.Bot.Interface.ChatBackground.Enums; + +namespace RxTelegram.Bot.Interface.ChatBackground; + +/// +/// The background is a PNG or TGV (gzipped subset of SVG with MIME type “application/x-tgwallpattern”) pattern to be combined with the background fill chosen by the user. +/// +public class BackgroundTypePattern : BackgroundType +{ + /// + /// Type of the background, always “pattern” + /// + public override BackgroundTypes Type { get; set; } = BackgroundTypes.Pattern; + + /// + /// Document with the pattern + /// + public Document Document { get; set; } + + /// + /// The background fill that is combined with the pattern + /// + public BackgroundFill Fill { get; set; } + + /// + /// Intensity of the pattern when it is shown above the filled background; 0-100 + /// + public int Intensity { get; set; } + + /// + /// Optional. True, if the background fill must be applied only to the pattern itself. All other pixels are black in this case. For dark themes only + /// + public bool IsInverted { get; set; } + + /// + /// Optional. True, if the background moves slightly when the device is tilted + /// + public bool IsMoving { get; set; } +} diff --git a/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundTypeWallpaper.cs b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundTypeWallpaper.cs new file mode 100644 index 0000000..b9db881 --- /dev/null +++ b/src/RxTelegram.Bot/Interface/ChatBackground/BackgroundTypeWallpaper.cs @@ -0,0 +1,32 @@ +using RxTelegram.Bot.Interface.BaseTypes; +using RxTelegram.Bot.Interface.ChatBackground.Enums; + +namespace RxTelegram.Bot.Interface.ChatBackground; + +public class BackgroundTypeWallpaper : BackgroundType +{ + /// + /// Type of the background, always “wallpaper” + /// + public override BackgroundTypes Type { get; set; } = BackgroundTypes.Wallpaper; + + /// + /// Document with the wallpaper + /// + public Document Document { get; set; } + + /// + /// Dimming of the background in dark themes, as a percentage; 0-100 + /// + public int DarkThemeDimming { get; set; } + + /// + /// Optional. True, if the wallpaper is downscaled to fit in a 450x450 square and then box-blurred with radius 12 + /// + public bool IsBlurred { get; set; } + + /// + /// Optional. True, if the background moves slightly when the device is tilted + /// + public bool IsMoving { get; set; } +} diff --git a/src/RxTelegram.Bot/Interface/ChatBackground/ChatBackground.cs b/src/RxTelegram.Bot/Interface/ChatBackground/ChatBackground.cs new file mode 100644 index 0000000..5ddb5c3 --- /dev/null +++ b/src/RxTelegram.Bot/Interface/ChatBackground/ChatBackground.cs @@ -0,0 +1,12 @@ +namespace RxTelegram.Bot.Interface.ChatBackground; + +/// +/// This object represents a chat background. +/// +public class ChatBackground +{ + /// + /// Type of the background + /// + public BackgroundType Type { get; set; } +} diff --git a/src/RxTelegram.Bot/Interface/ChatBackground/Enums/BackgroundFillTypes.cs b/src/RxTelegram.Bot/Interface/ChatBackground/Enums/BackgroundFillTypes.cs new file mode 100644 index 0000000..9f464f0 --- /dev/null +++ b/src/RxTelegram.Bot/Interface/ChatBackground/Enums/BackgroundFillTypes.cs @@ -0,0 +1,15 @@ +using RxTelegram.Bot.Utils.MultiType; + +namespace RxTelegram.Bot.Interface.ChatBackground.Enums; + +public enum BackgroundFillTypes +{ + [ImplementationType(typeof(BackgroundFillFreeformGradient))] + FreeformGradient, + + [ImplementationType(typeof(BackgroundFillGradient))] + Gradient, + + [ImplementationType(typeof(BackgroundFillSolid))] + Solid +} diff --git a/src/RxTelegram.Bot/Interface/ChatBackground/Enums/BackgroundTypes.cs b/src/RxTelegram.Bot/Interface/ChatBackground/Enums/BackgroundTypes.cs new file mode 100644 index 0000000..ea0e05a --- /dev/null +++ b/src/RxTelegram.Bot/Interface/ChatBackground/Enums/BackgroundTypes.cs @@ -0,0 +1,18 @@ +using RxTelegram.Bot.Utils.MultiType; + +namespace RxTelegram.Bot.Interface.ChatBackground.Enums; + +public enum BackgroundTypes +{ + [ImplementationType(typeof(BackgroundTypeChatTheme))] + ChatTheme, + + [ImplementationType(typeof(BackgroundTypeFill))] + Fill, + + [ImplementationType(typeof(BackgroundTypePattern))] + Pattern, + + [ImplementationType(typeof(BackgroundTypeWallpaper))] + Wallpaper +} diff --git a/src/RxTelegram.Bot/RxTelegram.Bot.csproj b/src/RxTelegram.Bot/RxTelegram.Bot.csproj index 2c53e74..1dc2697 100644 --- a/src/RxTelegram.Bot/RxTelegram.Bot.csproj +++ b/src/RxTelegram.Bot/RxTelegram.Bot.csproj @@ -10,7 +10,7 @@ https://github.com/RxTelegram/RxTelegram.Bot git Telegram;Bot;Api;Rx;Reactive;Observable;RxTelegram;RxTelegram.Bot - 7.2.0 + 7.3.0 icon.png true bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml diff --git a/src/RxTelegram.Bot/TelegramBot.cs b/src/RxTelegram.Bot/TelegramBot.cs index 31df71d..b402c9b 100644 --- a/src/RxTelegram.Bot/TelegramBot.cs +++ b/src/RxTelegram.Bot/TelegramBot.cs @@ -217,8 +217,8 @@ public Task EditMessageLiveLocation( /// ChatId for the request. /// Propagates notification that operations should be canceled. /// Returns a object on success. - public Task GetChat(GetChat getChat, CancellationToken cancellationToken = default) => - Post("getChat", getChat, cancellationToken); + public Task GetChat(GetChat getChat, CancellationToken cancellationToken = default) => + Post("getChat", getChat, cancellationToken); /// /// Use this method to get information about a member of a chat. @@ -1283,9 +1283,9 @@ public Task DeleteMessages(DeleteMessages deleteMessages, CancellationToke /// /// MessageIds to forward /// Propagates notification that operations should be canceled. - /// Returns True on success. - public Task ForwardMessages(ForwardMessages forwardMessages, CancellationToken cancellationToken = default) => - Post("forwardMessages", forwardMessages, cancellationToken); + /// On success, an array of with the send messages is returned. + public Task ForwardMessages(ForwardMessages forwardMessages, CancellationToken cancellationToken = default) => + Post("forwardMessages", forwardMessages, cancellationToken); /// /// Use this method to get the list of boosts added to a chat by a user. Requires administrator rights in the chat. @@ -1317,4 +1317,17 @@ public Task GetBusinessConnection( /// Returns True on success. public Task ReplaceStickerInSet(ReplaceStickerInSet replaceStickerInSet, CancellationToken cancellationToken = default) => Post("replaceStickerInSet", replaceStickerInSet, cancellationToken); + + /// + /// 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. + /// + /// Information about the messages to copy + /// Propagates notification that operations should be canceled. + /// Returns an array of on success. + public Task CopyMessages(CopyMessages copyMessages, CancellationToken cancellationToken = default) => + Post("copyMessages", copyMessages, cancellationToken); } diff --git a/src/RxTelegram.Bot/Utils/Converter/MultiTypeClassConverter.cs b/src/RxTelegram.Bot/Utils/Converter/MultiTypeClassConverter.cs index 6f0897b..085b2ea 100644 --- a/src/RxTelegram.Bot/Utils/Converter/MultiTypeClassConverter.cs +++ b/src/RxTelegram.Bot/Utils/Converter/MultiTypeClassConverter.cs @@ -17,6 +17,12 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist CheckForValidInterfaces(objectType); var distinguishingProperty = GetNameOfDistinguishingProperty(objectType); var jsonObject = JObject.Load(reader); + if (!jsonObject.HasValues) + { + return null; + } + jsonObject[distinguishingProperty] = ToPascalCaseIfNecessary(jsonObject[distinguishingProperty] + ?.ToString()); var valueToDefineResultType = jsonObject.GetValue(distinguishingProperty) ?? throw new InvalidOperationException("The property is not found"); var resultTypeEnum = GetEnumOfGenericInterface(objectType); @@ -40,6 +46,15 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist return objectInstance; } + private static JToken ToPascalCaseIfNecessary(string toString) + { + var words = toString.Split(new[] { '-', '_' }, StringSplitOptions.RemoveEmptyEntries) + .Select(word => word.Substring(0, 1).ToUpper() + + word.Substring(1).ToLower()); + + return string.Concat(words); + } + private static Type GetEnumOfGenericInterface(Type objectType) { var interfaces = objectType.GetInterfaces(); diff --git a/src/RxTelegram.Bot/Utils/HexToRGB24.cs b/src/RxTelegram.Bot/Utils/HexToRGB24.cs new file mode 100644 index 0000000..541dd52 --- /dev/null +++ b/src/RxTelegram.Bot/Utils/HexToRGB24.cs @@ -0,0 +1,40 @@ +using System; +using System.Globalization; + +namespace RxTelegram.Bot.Utils; + +public static class HexToRgb24 +{ + public static int Convert(string hexColor) + { + var formatHexString = FormatHexString(hexColor); + if (formatHexString.Length != 6) + { + throw new ArgumentException("Invalid hex color", nameof(hexColor)); + } + return int.Parse(formatHexString, NumberStyles.HexNumber); + } + + public static bool TryConvert(string hexColor, out int result) + { + var formatHexString = FormatHexString(hexColor); + if (formatHexString.Length == 6) + { + return int.TryParse(FormatHexString(hexColor), NumberStyles.HexNumber, null, out result); + } + + result = -1; + return false; + } + + private static string FormatHexString(string hexColor) + { + hexColor = hexColor.TrimStart('#'); + if (hexColor.Length == 3) + { + hexColor = string.Concat(hexColor[0], hexColor[0], hexColor[1], hexColor[1], hexColor[2], hexColor[2]); + } + + return hexColor; + } +} diff --git a/src/RxTelegram.Bot/Validation/ValidationResultFactory.cs b/src/RxTelegram.Bot/Validation/ValidationResultFactory.cs index fa2ba95..3b82627 100644 --- a/src/RxTelegram.Bot/Validation/ValidationResultFactory.cs +++ b/src/RxTelegram.Bot/Validation/ValidationResultFactory.cs @@ -224,8 +224,6 @@ public static ValidationResult CreateValidation(this SendChatAct ValidationErrors.QuestionTooLong) .IsFalse(x => x.Options != null && x.Options.Count() > 1 && x.Options.Count() <= 10, ValidationErrors.InvalidOptionCount) - .IsFalse(x => x.Options != null && x.Options.All(y => y.Length > 0 && y.Length <= 100), - ValidationErrors.OptionStringTooLong) .IsTrue(x => x.Type == PollType.Quiz && x.CorrectOptionId == null, ValidationErrors.CorrectOptionRequired) .IsTrue(x => x.OpenPeriod.HasValue && x.CloseDate.HasValue, diff --git a/src/UnitTests/HexToRgb24Tests.cs b/src/UnitTests/HexToRgb24Tests.cs new file mode 100644 index 0000000..8a71100 --- /dev/null +++ b/src/UnitTests/HexToRgb24Tests.cs @@ -0,0 +1,62 @@ +using System; +using NUnit.Framework; +using RxTelegram.Bot.Utils; + +namespace RxTelegram.Bot.UnitTests; + +[TestFixture] +public class HexToRgb24Tests +{ + [TestCase("#FF0000", ExpectedResult = 16711680)] // Red + [TestCase("#00FF00", ExpectedResult = 65280)] // Green + [TestCase("#0000FF", ExpectedResult = 255)] // Blue + [TestCase("#000000", ExpectedResult = 0)] // Black + [TestCase("#FFFFFF", ExpectedResult = 16777215)] // White + [TestCase("#ABCDEF", ExpectedResult = 11259375)] // Random color + public int Convert_ValidHexColor_ReturnsRgbValue(string hexColor) => HexToRgb24.Convert(hexColor); + + [TestCase("#0000000")] + [TestCase("#00000000")] + public void Convert_InvalidHexLength_ThrowsArgumentException(string hexColor) => + Assert.Throws(() => HexToRgb24.Convert(hexColor)); + + [TestCase("#G00000")] + [TestCase("#00000G")] + public void Convert_InvalidHexColor_ThrowsFormatException(string hexColor) => + Assert.Throws(() => HexToRgb24.Convert(hexColor)); + + [TestCase("#0000000")] + [TestCase("#00000000")] + public void TryConvert_InvalidHexLength_ThrowsArgumentException(string hexColor) => + Assert.That(HexToRgb24.TryConvert(hexColor, out _), Is.False); + + [TestCase("#G00000")] + [TestCase("#00000G")] + public void TryConvert_InvalidHexColor_ThrowsFormatException(string hexColor) => + Assert.That(HexToRgb24.TryConvert(hexColor, out _), Is.False); + + [TestCase("#FF0000", ExpectedResult = true)] // Red + [TestCase("#00FF00", ExpectedResult = true)] // Green + [TestCase("#0000FF", ExpectedResult = true)] // Blue + [TestCase("#000000", ExpectedResult = true)] // Black + [TestCase("#FFFFFF", ExpectedResult = true)] // White + [TestCase("#ABCDEF", ExpectedResult = true)] // Random color + [TestCase("#G00000", ExpectedResult = false)] + [TestCase("#00000G", ExpectedResult = false)] + [TestCase("#0000000", ExpectedResult = false)] + [TestCase("#00000000", ExpectedResult = false)] + public bool TryConvert_ValidHexColor_ReturnsTrue(string hexColor) => HexToRgb24.TryConvert(hexColor, out _); + + [TestCase("#FF0000", 16711680)] // Red + [TestCase("#00FF00", 65280)] // Green + [TestCase("#0000FF", 255)] // Blue + [TestCase("#000000", 0)] // Black + [TestCase("#FFFFFF", 16777215)] // White + [TestCase("#ABCDEF", 11259375)] // Random color + public void TryConvert_ValidHexColor_ReturnsRgbValue(string hexColor, int expected) + { + HexToRgb24.TryConvert(hexColor, out var result); + Assert.That(result, Is.EqualTo(expected)); + } + +} diff --git a/src/UnitTests/JsonConverters/BackgroundTypeConverterTest.cs b/src/UnitTests/JsonConverters/BackgroundTypeConverterTest.cs new file mode 100644 index 0000000..ede0e5d --- /dev/null +++ b/src/UnitTests/JsonConverters/BackgroundTypeConverterTest.cs @@ -0,0 +1,56 @@ +using System; +using Newtonsoft.Json; +using NUnit.Framework; +using NUnit.Framework.Constraints; +using RxTelegram.Bot.Interface.ChatBackground; +using RxTelegram.Bot.Utils.Converter; + +namespace RxTelegram.Bot.UnitTests.JsonConverters; + +[TestFixture] +public class BackgroundTypeConverterTest +{ + private readonly JsonSerializerSettings _jsonSettings = new() + { + Converters = { new MultiTypeClassConverter() } + }; + + [Test] + [TestCase("chat_theme", typeof(BackgroundTypeChatTheme))] + [TestCase("fill", typeof(BackgroundTypeFill))] + [TestCase("pattern", typeof(BackgroundTypePattern))] + [TestCase("wallpaper", typeof(BackgroundTypeWallpaper))] + public void CanRead(string type, Type expectedType) + { + var json = $"{{\"type\":\"{type}\"}}"; + var actual = JsonConvert.DeserializeObject(json, _jsonSettings); + Assert.That(actual, Is.Not.Null); + Assert.That(actual.GetType(), Is.EqualTo(expectedType)); + } + + [Test] + public void CanReadNull() + { + const string json = "{}"; + var actual = JsonConvert.DeserializeObject(json, _jsonSettings); + Assert.That(actual, Is.Null); + } + + [Test] + [TestCase(typeof(BackgroundFillFreeformGradient), 0)] + [TestCase(typeof(BackgroundFillGradient), 1)] + [TestCase(typeof(BackgroundFillSolid), 2)] + public void CanWrite(Type type, int expectedType) + { + var instance = Activator.CreateInstance(type); + var json = JsonConvert.SerializeObject(instance, _jsonSettings); + Assert.That(json, new StartsWithConstraint($"{{\"Type\":{expectedType}")); + } + + [Test] + public void CanWriteNull() + { + var json = JsonConvert.SerializeObject(null, _jsonSettings); + Assert.That(json, Is.EqualTo("null")); + } +}