diff --git a/crates/teloxide-core/schema.ron b/crates/teloxide-core/schema.ron index dfe1e459..d814072e 100644 --- a/crates/teloxide-core/schema.ron +++ b/crates/teloxide-core/schema.ron @@ -230,6 +230,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)") ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "text", ty: String, @@ -304,6 +309,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)"), ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "from_chat_id", ty: RawTy("Recipient"), @@ -344,6 +354,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)"), ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "from_chat_id", ty: RawTy("Recipient"), @@ -423,6 +438,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)") ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "photo", ty: RawTy("InputFile"), @@ -503,6 +523,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)"), ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "audio", ty: RawTy("InputFile"), @@ -603,6 +628,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)"), ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "document", ty: RawTy("InputFile"), @@ -696,6 +726,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)"), ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "video", ty: RawTy("InputFile"), @@ -802,6 +837,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)"), ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "animation", ty: RawTy("InputFile"), @@ -898,7 +938,7 @@ Schema( "Message": "https://core.telegram.org/bots/api#message", }, ), - tg_doc: "https://core.telegram.org/bots/api#sendaudio", + tg_doc: "https://core.telegram.org/bots/api#sendvoice", tg_category: "Available methods", params: [ Param( @@ -906,6 +946,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)"), ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "voice", ty: RawTy("InputFile"), @@ -986,6 +1031,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)"), ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "video_note", ty: RawTy("InputFile"), @@ -1064,6 +1114,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)") ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "media", ty: ArrayOf(RawTy("InputMedia")), @@ -1109,6 +1164,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)"), ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "latitude", ty: f64, @@ -1392,6 +1452,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)") ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "latitude", ty: f64, @@ -1486,6 +1551,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)") ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "phone_number", ty: String, @@ -1560,6 +1630,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)") ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "question", ty: String, @@ -1674,6 +1749,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)") ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "emoji", ty: Option(RawTy("DiceEmoji")), @@ -1942,11 +2022,6 @@ Schema( ty: Option(bool), descr: Doc(md: "Pass True, if the administrator can access the chat event log, chat statistics, message statistics in channels, see channel members, see anonymous administrators in supergroups and ignore slow mode. Implied by any other administrator privilege"), ), - Param( - name: "can_change_info", - ty: Option(bool), - descr: Doc(md: "Pass True, if the administrator can change chat title, photo and other settings") - ), Param( name: "can_post_messages", ty: Option(bool), @@ -1967,26 +2042,36 @@ Schema( ty: Option(bool), descr: Doc(md: "Pass True, if the administrator can manage video chats, supergroups only") ), - Param( - name: "can_invite_users", - ty: Option(bool), - descr: Doc(md: "Pass True, if the administrator can invite new users to the chat") - ), Param( name: "can_restrict_members", ty: Option(bool), descr: Doc(md: "Pass True, if the administrator can restrict, ban or unban chat members") - ), - Param( - name: "can_pin_messages", - ty: Option(bool), - descr: Doc(md: "Pass True, if the administrator can pin messages, supergroups only") ), Param( name: "can_promote_members", ty: Option(bool), descr: Doc(md: "Pass True, if the administrator can add new administrators with a subset of their own privileges or demote administrators that he has promoted, directly or indirectly (promoted by administrators that were appointed by him)") ), + Param( + name: "can_change_info", + ty: Option(bool), + descr: Doc(md: "Pass True, if the administrator can change chat title, photo and other settings") + ), + Param( + name: "can_invite_users", + ty: Option(bool), + descr: Doc(md: "Pass True, if the administrator can invite new users to the chat") + ), + Param( + name: "can_pin_messages", + ty: Option(bool), + descr: Doc(md: "Pass True, if the administrator can pin messages, supergroups only") + ), + Param( + name: "can_manage_topics", + ty: Option(bool), + descr: Doc(md: "Pass True if the user is allowed to create, rename, close, and reopen forum topics, supergroups only") + ), ], ), Method( @@ -2489,6 +2574,149 @@ Schema( ), ], ), + Method( + names: ("getForumTopicIconStickers", "GetForumTopicIconStickers", "get_forum_topic_icon_stickers"), + return_ty: ArrayOf(RawTy("Sticker")), + doc: Doc(md: "Use this method to get custom emoji stickers, which can be used as a forum topic icon by any user. Requires no parameters. Returns an Array of `Sticker` objects."), + tg_doc: "https://core.telegram.org/bots/api#getforumtopiciconstickers", + tg_category: "Available methods", + params: [], + ), + Method( + names: ("createForumTopic", "CreateForumTopic", "create_forum_topic"), + return_ty: RawTy("ForumTopic"), + doc: Doc(md: "Use this method to create a topic in a forum supergroup chat. The bot must be an administrator in the chat for this to work and must have the _can\\_manage\\_topics_ administrator rights. Returns information about the created topic as a `ForumTopic` object."), + tg_doc: "https://core.telegram.org/bots/api#createforumtopic", + tg_category: "Available methods", + params: [ + Param( + name: "chat_id", + ty: RawTy("Recipient"), + descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)") + ), + Param( + name: "name", + ty: String, + descr: Doc(md: "Topic name, 1-128 characters") + ), + Param( + name: "icon_color", + // FIXME: use an Rgb or something + ty: u32, + descr: Doc(md: "Color of the topic icon in RGB format. Currently, must be one of 7322096 (0x6FB9F0), 16766590 (0xFFD67E), 13338331 (0xCB86DB), 9367192 (0x8EEE98), 16749490 (0xFF93B2), or 16478047 (0xFB6F5F)") + ), + Param( + name: "icon_custom_emoji_id", + ty: String, + descr: Doc(md: "Unique identifier of the custom emoji shown as the topic icon. Use `getForumTopicIconStickers` to get all allowed custom emoji identifiers.") + ), + ], + ), + Method( + names: ("editForumTopic", "EditForumTopic", "edit_forum_topic"), + return_ty: True, + doc: Doc(md: "Use this method to edit name and icon of a topic in a forum supergroup chat. The bot must be an administrator in the chat for this to work and must have _can\\_manage\\_topics_ administrator rights, unless it is the creator of the topic. Returns True on success."), + tg_doc: "https://core.telegram.org/bots/api#editforumtopic", + tg_category: "Available methods", + params: [ + Param( + name: "chat_id", + ty: RawTy("Recipient"), + descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)") + ), + Param( + name: "message_thread_id", + ty: i32, + descr: Doc(md: "Unique identifier for the target message thread of the forum topic"), + ), + Param( + name: "name", + ty: String, + descr: Doc(md: "Topic name, 1-128 characters") + ), + Param( + name: "icon_custom_emoji_id", + ty: String, + descr: Doc(md: "Unique identifier of the custom emoji shown as the topic icon. Use `getForumTopicIconStickers` to get all allowed custom emoji identifiers.") + ), + ], + ), + Method( + names: ("closeForumTopic", "CloseForumTopic", "close_forum_topic"), + return_ty: True, + doc: Doc(md: "Use this method to close an open topic in a forum supergroup chat. The bot must be an administrator in the chat for this to work and must have the _can\\_manage\\_topics_ administrator rights, unless it is the creator of the topic. Returns True on success."), + tg_doc: "https://core.telegram.org/bots/api#closeforumtopic", + tg_category: "Available methods", + params: [ + Param( + name: "chat_id", + ty: RawTy("Recipient"), + descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)") + ), + Param( + name: "message_thread_id", + ty: i32, + descr: Doc(md: "Unique identifier for the target message thread of the forum topic"), + ), + ], + ), + Method( + names: ("reopenForumTopic", "ReopenForumTopic", "reopen_forum_topic"), + return_ty: True, + doc: Doc(md: "Use this method to reopen a closed topic in a forum supergroup chat. The bot must be an administrator in the chat for this to work and must have the _can\\_manage\\_topics_ administrator rights, unless it is the creator of the topic. Returns True on success."), + tg_doc: "https://core.telegram.org/bots/api#reopenforumtopic", + tg_category: "Available methods", + params: [ + Param( + name: "chat_id", + ty: RawTy("Recipient"), + descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)") + ), + Param( + name: "message_thread_id", + ty: i32, + descr: Doc(md: "Unique identifier for the target message thread of the forum topic"), + ), + ], + ), + Method( + names: ("deleteForumTopic", "DeleteForumTopic", "delete_forum_topic"), + return_ty: True, + doc: Doc(md: "Use this method to delete a forum topic along with all its messages in a forum supergroup chat. The bot must be an administrator in the chat for this to work and must have the _can\\_delete\\_messages_ administrator rights. Returns True on success."), + tg_doc: "https://core.telegram.org/bots/api#deleteforumtopic", + tg_category: "Available methods", + params: [ + Param( + name: "chat_id", + ty: RawTy("Recipient"), + descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)") + ), + Param( + name: "message_thread_id", + ty: i32, + descr: Doc(md: "Unique identifier for the target message thread of the forum topic"), + ), + ], + ), + Method( + names: ("unpinAllForumTopicMessages", "UnpinAllForumTopicMessages", "unpin_all_forum_topic_messages"), + return_ty: True, + doc: Doc(md: "Use this method to clear the list of pinned messages in a forum topic. The bot must be an administrator in the chat for this to work and must have the _can\\_pin\\_messages_ administrator right in the supergroup. Returns True on success."), + tg_doc: "https://core.telegram.org/bots/api#deleteforumtopic", + tg_category: "Available methods", + params: [ + Param( + name: "chat_id", + ty: RawTy("Recipient"), + descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`)") + ), + Param( + name: "message_thread_id", + ty: i32, + descr: Doc(md: "Unique identifier for the target message thread of the forum topic"), + ), + ], + ), Method( names: ("answerCallbackQuery", "AnswerCallbackQuery", "answer_callback_query"), return_ty: True, @@ -3106,6 +3334,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target chat or username of the target channel (in the format `@channelusername`).") ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "sticker", ty: RawTy("InputFile"), @@ -3359,6 +3592,11 @@ Schema( ty: RawTy("Recipient"), descr: Doc(md: "Unique identifier for the target private chat"), ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "title", ty: String, @@ -3711,6 +3949,11 @@ Schema( ty: u32, descr: Doc(md: "Unique identifier for the target chat"), ), + Param( + name: "message_thread_id", + ty: Option(i32), + descr: Doc(md: "Unique identifier for the target message thread (topic) of the forum; for forum supergroups only"), + ), Param( name: "game_short_name", ty: String, diff --git a/crates/teloxide-core/src/adaptors/auto_send.rs b/crates/teloxide-core/src/adaptors/auto_send.rs index 607d69c0..2bd9c075 100644 --- a/crates/teloxide-core/src/adaptors/auto_send.rs +++ b/crates/teloxide-core/src/adaptors/auto_send.rs @@ -120,6 +120,13 @@ where get_chat_member, set_chat_sticker_set, delete_chat_sticker_set, + get_forum_topic_icon_stickers, + create_forum_topic, + edit_forum_topic, + close_forum_topic, + reopen_forum_topic, + delete_forum_topic, + unpin_all_forum_topic_messages, answer_callback_query, set_my_commands, get_my_commands, diff --git a/crates/teloxide-core/src/adaptors/cache_me.rs b/crates/teloxide-core/src/adaptors/cache_me.rs index 86ee8118..c2b3537f 100644 --- a/crates/teloxide-core/src/adaptors/cache_me.rs +++ b/crates/teloxide-core/src/adaptors/cache_me.rs @@ -144,6 +144,13 @@ where get_chat_member, set_chat_sticker_set, delete_chat_sticker_set, + get_forum_topic_icon_stickers, + create_forum_topic, + edit_forum_topic, + close_forum_topic, + reopen_forum_topic, + delete_forum_topic, + unpin_all_forum_topic_messages, answer_callback_query, set_my_commands, get_my_commands, diff --git a/crates/teloxide-core/src/adaptors/erased.rs b/crates/teloxide-core/src/adaptors/erased.rs index f5d2d6bf..2041d22c 100644 --- a/crates/teloxide-core/src/adaptors/erased.rs +++ b/crates/teloxide-core/src/adaptors/erased.rs @@ -233,6 +233,13 @@ where get_chat_member, set_chat_sticker_set, delete_chat_sticker_set, + get_forum_topic_icon_stickers, + create_forum_topic, + edit_forum_topic, + close_forum_topic, + reopen_forum_topic, + delete_forum_topic, + unpin_all_forum_topic_messages, answer_callback_query, set_my_commands, get_my_commands, @@ -605,6 +612,50 @@ trait ErasableRequester<'a> { chat_id: Recipient, ) -> ErasedRequest<'a, DeleteChatStickerSet, Self::Err>; + fn get_forum_topic_icon_stickers( + &self, + ) -> ErasedRequest<'a, GetForumTopicIconStickers, Self::Err>; + + fn create_forum_topic( + &self, + chat_id: Recipient, + name: String, + icon_color: u32, + icon_custom_emoji_id: String, + ) -> ErasedRequest<'a, CreateForumTopic, Self::Err>; + + fn edit_forum_topic( + &self, + chat_id: Recipient, + message_thread_id: i32, + name: String, + icon_custom_emoji_id: String, + ) -> ErasedRequest<'a, EditForumTopic, Self::Err>; + + fn close_forum_topic( + &self, + chat_id: Recipient, + message_thread_id: i32, + ) -> ErasedRequest<'a, CloseForumTopic, Self::Err>; + + fn reopen_forum_topic( + &self, + chat_id: Recipient, + message_thread_id: i32, + ) -> ErasedRequest<'a, ReopenForumTopic, Self::Err>; + + fn delete_forum_topic( + &self, + chat_id: Recipient, + message_thread_id: i32, + ) -> ErasedRequest<'a, DeleteForumTopic, Self::Err>; + + fn unpin_all_forum_topic_messages( + &self, + chat_id: Recipient, + message_thread_id: i32, + ) -> ErasedRequest<'a, UnpinAllForumTopicMessages, Self::Err>; + fn answer_callback_query( &self, callback_query_id: String, @@ -1279,6 +1330,65 @@ where Requester::delete_chat_sticker_set(self, chat_id).erase() } + fn get_forum_topic_icon_stickers( + &self, + ) -> ErasedRequest<'a, GetForumTopicIconStickers, Self::Err> { + Requester::get_forum_topic_icon_stickers(self).erase() + } + + fn create_forum_topic( + &self, + chat_id: Recipient, + name: String, + icon_color: u32, + icon_custom_emoji_id: String, + ) -> ErasedRequest<'a, CreateForumTopic, Self::Err> { + Requester::create_forum_topic(self, chat_id, name, icon_color, icon_custom_emoji_id).erase() + } + + fn edit_forum_topic( + &self, + chat_id: Recipient, + message_thread_id: i32, + name: String, + icon_custom_emoji_id: String, + ) -> ErasedRequest<'a, EditForumTopic, Self::Err> { + Requester::edit_forum_topic(self, chat_id, message_thread_id, name, icon_custom_emoji_id) + .erase() + } + + fn close_forum_topic( + &self, + chat_id: Recipient, + message_thread_id: i32, + ) -> ErasedRequest<'a, CloseForumTopic, Self::Err> { + Requester::close_forum_topic(self, chat_id, message_thread_id).erase() + } + + fn reopen_forum_topic( + &self, + chat_id: Recipient, + message_thread_id: i32, + ) -> ErasedRequest<'a, ReopenForumTopic, Self::Err> { + Requester::reopen_forum_topic(self, chat_id, message_thread_id).erase() + } + + fn delete_forum_topic( + &self, + chat_id: Recipient, + message_thread_id: i32, + ) -> ErasedRequest<'a, DeleteForumTopic, Self::Err> { + Requester::delete_forum_topic(self, chat_id, message_thread_id).erase() + } + + fn unpin_all_forum_topic_messages( + &self, + chat_id: Recipient, + message_thread_id: i32, + ) -> ErasedRequest<'a, UnpinAllForumTopicMessages, Self::Err> { + Requester::unpin_all_forum_topic_messages(self, chat_id, message_thread_id).erase() + } + fn answer_callback_query( &self, callback_query_id: String, diff --git a/crates/teloxide-core/src/adaptors/parse_mode.rs b/crates/teloxide-core/src/adaptors/parse_mode.rs index cd6e6870..d69c275b 100644 --- a/crates/teloxide-core/src/adaptors/parse_mode.rs +++ b/crates/teloxide-core/src/adaptors/parse_mode.rs @@ -143,6 +143,13 @@ impl Requester for DefaultParseMode { get_chat_member, set_chat_sticker_set, delete_chat_sticker_set, + get_forum_topic_icon_stickers, + create_forum_topic, + edit_forum_topic, + close_forum_topic, + reopen_forum_topic, + delete_forum_topic, + unpin_all_forum_topic_messages, answer_callback_query, set_my_commands, get_my_commands, diff --git a/crates/teloxide-core/src/adaptors/throttle/requester_impl.rs b/crates/teloxide-core/src/adaptors/throttle/requester_impl.rs index e7817f50..a0d5965c 100644 --- a/crates/teloxide-core/src/adaptors/throttle/requester_impl.rs +++ b/crates/teloxide-core/src/adaptors/throttle/requester_impl.rs @@ -127,6 +127,13 @@ where get_chat_member, set_chat_sticker_set, delete_chat_sticker_set, + get_forum_topic_icon_stickers, + create_forum_topic, + edit_forum_topic, + close_forum_topic, + reopen_forum_topic, + delete_forum_topic, + unpin_all_forum_topic_messages, answer_callback_query, set_my_commands, get_my_commands, diff --git a/crates/teloxide-core/src/adaptors/trace.rs b/crates/teloxide-core/src/adaptors/trace.rs index bcc43828..189e1c96 100644 --- a/crates/teloxide-core/src/adaptors/trace.rs +++ b/crates/teloxide-core/src/adaptors/trace.rs @@ -173,6 +173,13 @@ where get_chat_member, set_chat_sticker_set, delete_chat_sticker_set, + get_forum_topic_icon_stickers, + create_forum_topic, + edit_forum_topic, + close_forum_topic, + reopen_forum_topic, + delete_forum_topic, + unpin_all_forum_topic_messages, answer_callback_query, set_my_commands, get_my_commands, diff --git a/crates/teloxide-core/src/bot/api.rs b/crates/teloxide-core/src/bot/api.rs index 1572a371..8a4b8140 100644 --- a/crates/teloxide-core/src/bot/api.rs +++ b/crates/teloxide-core/src/bot/api.rs @@ -644,6 +644,107 @@ impl Requester for Bot { Self::DeleteChatStickerSet::new(self.clone(), payloads::DeleteChatStickerSet::new(chat_id)) } + type GetForumTopicIconStickers = JsonRequest; + + fn get_forum_topic_icon_stickers(&self) -> Self::GetForumTopicIconStickers { + Self::GetForumTopicIconStickers::new( + self.clone(), + payloads::GetForumTopicIconStickers::new(), + ) + } + + type CreateForumTopic = JsonRequest; + + fn create_forum_topic( + &self, + chat_id: C, + name: N, + icon_color: u32, + icon_custom_emoji_id: I, + ) -> Self::CreateForumTopic + where + C: Into, + N: Into, + I: Into, + { + Self::CreateForumTopic::new( + self.clone(), + payloads::CreateForumTopic::new(chat_id, name, icon_color, icon_custom_emoji_id), + ) + } + + type EditForumTopic = JsonRequest; + + fn edit_forum_topic( + &self, + chat_id: C, + message_thread_id: i32, + name: N, + icon_custom_emoji_id: I, + ) -> Self::EditForumTopic + where + C: Into, + N: Into, + I: Into, + { + Self::EditForumTopic::new( + self.clone(), + payloads::EditForumTopic::new(chat_id, message_thread_id, name, icon_custom_emoji_id), + ) + } + + type CloseForumTopic = JsonRequest; + + fn close_forum_topic(&self, chat_id: C, message_thread_id: i32) -> Self::CloseForumTopic + where + C: Into, + { + Self::CloseForumTopic::new( + self.clone(), + payloads::CloseForumTopic::new(chat_id, message_thread_id), + ) + } + + type ReopenForumTopic = JsonRequest; + + fn reopen_forum_topic(&self, chat_id: C, message_thread_id: i32) -> Self::ReopenForumTopic + where + C: Into, + { + Self::ReopenForumTopic::new( + self.clone(), + payloads::ReopenForumTopic::new(chat_id, message_thread_id), + ) + } + + type DeleteForumTopic = JsonRequest; + + fn delete_forum_topic(&self, chat_id: C, message_thread_id: i32) -> Self::DeleteForumTopic + where + C: Into, + { + Self::DeleteForumTopic::new( + self.clone(), + payloads::DeleteForumTopic::new(chat_id, message_thread_id), + ) + } + + type UnpinAllForumTopicMessages = JsonRequest; + + fn unpin_all_forum_topic_messages( + &self, + chat_id: C, + message_thread_id: i32, + ) -> Self::UnpinAllForumTopicMessages + where + C: Into, + { + Self::UnpinAllForumTopicMessages::new( + self.clone(), + payloads::UnpinAllForumTopicMessages::new(chat_id, message_thread_id), + ) + } + type AnswerCallbackQuery = JsonRequest; fn answer_callback_query(&self, callback_query_id: C) -> Self::AnswerCallbackQuery diff --git a/crates/teloxide-core/src/codegen.rs b/crates/teloxide-core/src/codegen.rs index 4c71c165..477ebc9f 100644 --- a/crates/teloxide-core/src/codegen.rs +++ b/crates/teloxide-core/src/codegen.rs @@ -15,7 +15,6 @@ pub(crate) mod schema; use std::{ fs, - io::{Read, Write}, path::{Path, PathBuf}, }; @@ -79,9 +78,7 @@ pub fn ensure_files_contents<'a>( let mut err_count = 0; for (path, contents) in files_and_contents { - let mut file = fs::File::options().read(true).write(true).create(true).open(path).unwrap(); - let mut old_contents = String::with_capacity(contents.len()); - file.read_to_string(&mut old_contents).unwrap(); + let old_contents = fs::read_to_string(path).unwrap(); if normalize_newlines(&old_contents) == normalize_newlines(contents) { // File is already up to date. @@ -98,7 +95,7 @@ pub fn ensure_files_contents<'a>( if let Some(parent) = path.parent() { let _ = fs::create_dir_all(parent); } - file.write_all(contents.as_bytes()).unwrap(); + fs::write(path, contents.as_bytes()).unwrap(); } let (s, were) = match err_count { diff --git a/crates/teloxide-core/src/local_macros.rs b/crates/teloxide-core/src/local_macros.rs index de69f36d..be1a4fc1 100644 --- a/crates/teloxide-core/src/local_macros.rs +++ b/crates/teloxide-core/src/local_macros.rs @@ -908,6 +908,66 @@ macro_rules! requester_forward { $body!(delete_chat_sticker_set this (chat_id: C)) } }; + (@method get_forum_topic_icon_stickers $body:ident $ty:ident) => { + type GetForumTopicIconStickers = $ty![GetForumTopicIconStickers]; + + fn get_forum_topic_icon_stickers(&self, ) -> Self::GetForumTopicIconStickers { + let this = self; + $body!(get_forum_topic_icon_stickers this ()) + } + }; + (@method create_forum_topic $body:ident $ty:ident) => { + type CreateForumTopic = $ty![CreateForumTopic]; + + fn create_forum_topic(&self, chat_id: C, name: N, icon_color: u32, icon_custom_emoji_id: I) -> Self::CreateForumTopic where C: Into, + N: Into, + I: Into { + let this = self; + $body!(create_forum_topic this (chat_id: C, name: N, icon_color: u32, icon_custom_emoji_id: I)) + } + }; + (@method edit_forum_topic $body:ident $ty:ident) => { + type EditForumTopic = $ty![EditForumTopic]; + + fn edit_forum_topic(&self, chat_id: C, message_thread_id: i32, name: N, icon_custom_emoji_id: I) -> Self::EditForumTopic where C: Into, + N: Into, + I: Into { + let this = self; + $body!(edit_forum_topic this (chat_id: C, message_thread_id: i32, name: N, icon_custom_emoji_id: I)) + } + }; + (@method close_forum_topic $body:ident $ty:ident) => { + type CloseForumTopic = $ty![CloseForumTopic]; + + fn close_forum_topic(&self, chat_id: C, message_thread_id: i32) -> Self::CloseForumTopic where C: Into { + let this = self; + $body!(close_forum_topic this (chat_id: C, message_thread_id: i32)) + } + }; + (@method reopen_forum_topic $body:ident $ty:ident) => { + type ReopenForumTopic = $ty![ReopenForumTopic]; + + fn reopen_forum_topic(&self, chat_id: C, message_thread_id: i32) -> Self::ReopenForumTopic where C: Into { + let this = self; + $body!(reopen_forum_topic this (chat_id: C, message_thread_id: i32)) + } + }; + (@method delete_forum_topic $body:ident $ty:ident) => { + type DeleteForumTopic = $ty![DeleteForumTopic]; + + fn delete_forum_topic(&self, chat_id: C, message_thread_id: i32) -> Self::DeleteForumTopic where C: Into { + let this = self; + $body!(delete_forum_topic this (chat_id: C, message_thread_id: i32)) + } + }; + (@method unpin_all_forum_topic_messages $body:ident $ty:ident) => { + type UnpinAllForumTopicMessages = $ty![UnpinAllForumTopicMessages]; + + fn unpin_all_forum_topic_messages(&self, chat_id: C, message_thread_id: i32) -> Self::UnpinAllForumTopicMessages where C: Into { + let this = self; + $body!(unpin_all_forum_topic_messages this (chat_id: C, message_thread_id: i32)) + } + }; (@method answer_callback_query $body:ident $ty:ident) => { type AnswerCallbackQuery = $ty![AnswerCallbackQuery]; diff --git a/crates/teloxide-core/src/payloads.rs b/crates/teloxide-core/src/payloads.rs index ee37f29c..b74b1fb4 100644 --- a/crates/teloxide-core/src/payloads.rs +++ b/crates/teloxide-core/src/payloads.rs @@ -25,18 +25,22 @@ mod approve_chat_join_request; mod ban_chat_member; mod ban_chat_sender_chat; mod close; +mod close_forum_topic; mod copy_message; mod create_chat_invite_link; +mod create_forum_topic; mod create_invoice_link; mod create_new_sticker_set; mod decline_chat_join_request; mod delete_chat_photo; mod delete_chat_sticker_set; +mod delete_forum_topic; mod delete_message; mod delete_my_commands; mod delete_sticker_from_set; mod delete_webhook; mod edit_chat_invite_link; +mod edit_forum_topic; mod edit_message_caption; mod edit_message_caption_inline; mod edit_message_live_location; @@ -57,6 +61,7 @@ mod get_chat_members_count; mod get_chat_menu_button; mod get_custom_emoji_stickers; mod get_file; +mod get_forum_topic_icon_stickers; mod get_game_high_scores; mod get_me; mod get_my_commands; @@ -70,6 +75,7 @@ mod leave_chat; mod log_out; mod pin_chat_message; mod promote_chat_member; +mod reopen_forum_topic; mod restrict_chat_member; mod revoke_chat_invite_link; mod send_animation; @@ -111,6 +117,7 @@ mod stop_poll; mod unban_chat_member; mod unban_chat_sender_chat; mod unpin_all_chat_messages; +mod unpin_all_forum_topic_messages; mod unpin_chat_message; mod upload_sticker_file; @@ -124,18 +131,22 @@ pub use approve_chat_join_request::{ApproveChatJoinRequest, ApproveChatJoinReque pub use ban_chat_member::{BanChatMember, BanChatMemberSetters}; pub use ban_chat_sender_chat::{BanChatSenderChat, BanChatSenderChatSetters}; pub use close::{Close, CloseSetters}; +pub use close_forum_topic::{CloseForumTopic, CloseForumTopicSetters}; pub use copy_message::{CopyMessage, CopyMessageSetters}; pub use create_chat_invite_link::{CreateChatInviteLink, CreateChatInviteLinkSetters}; +pub use create_forum_topic::{CreateForumTopic, CreateForumTopicSetters}; pub use create_invoice_link::{CreateInvoiceLink, CreateInvoiceLinkSetters}; pub use create_new_sticker_set::{CreateNewStickerSet, CreateNewStickerSetSetters}; pub use decline_chat_join_request::{DeclineChatJoinRequest, DeclineChatJoinRequestSetters}; pub use delete_chat_photo::{DeleteChatPhoto, DeleteChatPhotoSetters}; pub use delete_chat_sticker_set::{DeleteChatStickerSet, DeleteChatStickerSetSetters}; +pub use delete_forum_topic::{DeleteForumTopic, DeleteForumTopicSetters}; pub use delete_message::{DeleteMessage, DeleteMessageSetters}; pub use delete_my_commands::{DeleteMyCommands, DeleteMyCommandsSetters}; pub use delete_sticker_from_set::{DeleteStickerFromSet, DeleteStickerFromSetSetters}; pub use delete_webhook::{DeleteWebhook, DeleteWebhookSetters}; pub use edit_chat_invite_link::{EditChatInviteLink, EditChatInviteLinkSetters}; +pub use edit_forum_topic::{EditForumTopic, EditForumTopicSetters}; pub use edit_message_caption::{EditMessageCaption, EditMessageCaptionSetters}; pub use edit_message_caption_inline::{EditMessageCaptionInline, EditMessageCaptionInlineSetters}; pub use edit_message_live_location::{EditMessageLiveLocation, EditMessageLiveLocationSetters}; @@ -160,6 +171,9 @@ pub use get_chat_members_count::{GetChatMembersCount, GetChatMembersCountSetters pub use get_chat_menu_button::{GetChatMenuButton, GetChatMenuButtonSetters}; pub use get_custom_emoji_stickers::{GetCustomEmojiStickers, GetCustomEmojiStickersSetters}; pub use get_file::{GetFile, GetFileSetters}; +pub use get_forum_topic_icon_stickers::{ + GetForumTopicIconStickers, GetForumTopicIconStickersSetters, +}; pub use get_game_high_scores::{GetGameHighScores, GetGameHighScoresSetters}; pub use get_me::{GetMe, GetMeSetters}; pub use get_my_commands::{GetMyCommands, GetMyCommandsSetters}; @@ -175,6 +189,7 @@ pub use leave_chat::{LeaveChat, LeaveChatSetters}; pub use log_out::{LogOut, LogOutSetters}; pub use pin_chat_message::{PinChatMessage, PinChatMessageSetters}; pub use promote_chat_member::{PromoteChatMember, PromoteChatMemberSetters}; +pub use reopen_forum_topic::{ReopenForumTopic, ReopenForumTopicSetters}; pub use restrict_chat_member::{RestrictChatMember, RestrictChatMemberSetters}; pub use revoke_chat_invite_link::{RevokeChatInviteLink, RevokeChatInviteLinkSetters}; pub use send_animation::{SendAnimation, SendAnimationSetters}; @@ -222,6 +237,9 @@ pub use stop_poll::{StopPoll, StopPollSetters}; pub use unban_chat_member::{UnbanChatMember, UnbanChatMemberSetters}; pub use unban_chat_sender_chat::{UnbanChatSenderChat, UnbanChatSenderChatSetters}; pub use unpin_all_chat_messages::{UnpinAllChatMessages, UnpinAllChatMessagesSetters}; +pub use unpin_all_forum_topic_messages::{ + UnpinAllForumTopicMessages, UnpinAllForumTopicMessagesSetters, +}; pub use unpin_chat_message::{UnpinChatMessage, UnpinChatMessageSetters}; pub use upload_sticker_file::{UploadStickerFile, UploadStickerFileSetters}; // END BLOCK payload_modules diff --git a/crates/teloxide-core/src/payloads/close_forum_topic.rs b/crates/teloxide-core/src/payloads/close_forum_topic.rs new file mode 100644 index 00000000..4e3d2674 --- /dev/null +++ b/crates/teloxide-core/src/payloads/close_forum_topic.rs @@ -0,0 +1,18 @@ +//! Generated by `codegen_payloads`, do not edit by hand. + +use serde::Serialize; + +use crate::types::{Recipient, True}; + +impl_payload! { + /// Use this method to close an open topic in a forum supergroup chat. The bot must be an administrator in the chat for this to work and must have the _can\_manage\_topics_ administrator rights, unless it is the creator of the topic. Returns True on success. + #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize)] + pub CloseForumTopic (CloseForumTopicSetters) => True { + required { + /// Unique identifier for the target chat or username of the target channel (in the format `@channelusername`) + pub chat_id: Recipient [into], + /// Unique identifier for the target message thread of the forum topic + pub message_thread_id: i32, + } + } +} diff --git a/crates/teloxide-core/src/payloads/copy_message.rs b/crates/teloxide-core/src/payloads/copy_message.rs index b614b79e..ec5e7a9c 100644 --- a/crates/teloxide-core/src/payloads/copy_message.rs +++ b/crates/teloxide-core/src/payloads/copy_message.rs @@ -20,6 +20,8 @@ impl_payload! { pub message_id: MessageId, } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// New caption for media, 0-1024 characters after entities parsing. If not specified, the original caption is kept pub caption: String [into], /// Mode for parsing entities in the photo caption. See [formatting options] for more details. diff --git a/crates/teloxide-core/src/payloads/create_forum_topic.rs b/crates/teloxide-core/src/payloads/create_forum_topic.rs new file mode 100644 index 00000000..a1412fb3 --- /dev/null +++ b/crates/teloxide-core/src/payloads/create_forum_topic.rs @@ -0,0 +1,22 @@ +//! Generated by `codegen_payloads`, do not edit by hand. + +use serde::Serialize; + +use crate::types::{ForumTopic, Recipient}; + +impl_payload! { + /// Use this method to create a topic in a forum supergroup chat. The bot must be an administrator in the chat for this to work and must have the _can\_manage\_topics_ administrator rights. Returns information about the created topic as a `ForumTopic` object. + #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize)] + pub CreateForumTopic (CreateForumTopicSetters) => ForumTopic { + required { + /// Unique identifier for the target chat or username of the target channel (in the format `@channelusername`) + pub chat_id: Recipient [into], + /// Topic name, 1-128 characters + pub name: String [into], + /// Color of the topic icon in RGB format. Currently, must be one of 7322096 (0x6FB9F0), 16766590 (0xFFD67E), 13338331 (0xCB86DB), 9367192 (0x8EEE98), 16749490 (0xFF93B2), or 16478047 (0xFB6F5F) + pub icon_color: u32, + /// Unique identifier of the custom emoji shown as the topic icon. Use `getForumTopicIconStickers` to get all allowed custom emoji identifiers. + pub icon_custom_emoji_id: String [into], + } + } +} diff --git a/crates/teloxide-core/src/payloads/delete_forum_topic.rs b/crates/teloxide-core/src/payloads/delete_forum_topic.rs new file mode 100644 index 00000000..05824937 --- /dev/null +++ b/crates/teloxide-core/src/payloads/delete_forum_topic.rs @@ -0,0 +1,18 @@ +//! Generated by `codegen_payloads`, do not edit by hand. + +use serde::Serialize; + +use crate::types::{Recipient, True}; + +impl_payload! { + /// Use this method to delete a forum topic along with all its messages in a forum supergroup chat. The bot must be an administrator in the chat for this to work and must have the _can\_delete\_messages_ administrator rights. Returns True on success. + #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize)] + pub DeleteForumTopic (DeleteForumTopicSetters) => True { + required { + /// Unique identifier for the target chat or username of the target channel (in the format `@channelusername`) + pub chat_id: Recipient [into], + /// Unique identifier for the target message thread of the forum topic + pub message_thread_id: i32, + } + } +} diff --git a/crates/teloxide-core/src/payloads/edit_forum_topic.rs b/crates/teloxide-core/src/payloads/edit_forum_topic.rs new file mode 100644 index 00000000..8cbcf916 --- /dev/null +++ b/crates/teloxide-core/src/payloads/edit_forum_topic.rs @@ -0,0 +1,22 @@ +//! Generated by `codegen_payloads`, do not edit by hand. + +use serde::Serialize; + +use crate::types::{Recipient, True}; + +impl_payload! { + /// Use this method to edit name and icon of a topic in a forum supergroup chat. The bot must be an administrator in the chat for this to work and must have _can\_manage\_topics_ administrator rights, unless it is the creator of the topic. Returns True on success. + #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize)] + pub EditForumTopic (EditForumTopicSetters) => True { + required { + /// Unique identifier for the target chat or username of the target channel (in the format `@channelusername`) + pub chat_id: Recipient [into], + /// Unique identifier for the target message thread of the forum topic + pub message_thread_id: i32, + /// Topic name, 1-128 characters + pub name: String [into], + /// Unique identifier of the custom emoji shown as the topic icon. Use `getForumTopicIconStickers` to get all allowed custom emoji identifiers. + pub icon_custom_emoji_id: String [into], + } + } +} diff --git a/crates/teloxide-core/src/payloads/forward_message.rs b/crates/teloxide-core/src/payloads/forward_message.rs index 1e4c079c..6b49df99 100644 --- a/crates/teloxide-core/src/payloads/forward_message.rs +++ b/crates/teloxide-core/src/payloads/forward_message.rs @@ -20,6 +20,8 @@ impl_payload! { pub message_id: MessageId, } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// Sends the message [silently]. Users will receive a notification with no sound. /// /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages diff --git a/crates/teloxide-core/src/payloads/get_forum_topic_icon_stickers.rs b/crates/teloxide-core/src/payloads/get_forum_topic_icon_stickers.rs new file mode 100644 index 00000000..e8926c57 --- /dev/null +++ b/crates/teloxide-core/src/payloads/get_forum_topic_icon_stickers.rs @@ -0,0 +1,13 @@ +//! Generated by `codegen_payloads`, do not edit by hand. + +use serde::Serialize; + +use crate::types::Sticker; + +impl_payload! { + /// Use this method to get custom emoji stickers, which can be used as a forum topic icon by any user. Requires no parameters. Returns an Array of `Sticker` objects. + #[derive(Debug, PartialEq, Eq, Hash, Default, Clone, Serialize)] + pub GetForumTopicIconStickers (GetForumTopicIconStickersSetters) => Vec { + + } +} diff --git a/crates/teloxide-core/src/payloads/promote_chat_member.rs b/crates/teloxide-core/src/payloads/promote_chat_member.rs index ece800f6..9b8bac40 100644 --- a/crates/teloxide-core/src/payloads/promote_chat_member.rs +++ b/crates/teloxide-core/src/payloads/promote_chat_member.rs @@ -19,8 +19,6 @@ impl_payload! { pub is_anonymous: bool, /// Pass True, if the administrator can access the chat event log, chat statistics, message statistics in channels, see channel members, see anonymous administrators in supergroups and ignore slow mode. Implied by any other administrator privilege pub can_manage_chat: bool, - /// Pass True, if the administrator can change chat title, photo and other settings - pub can_change_info: bool, /// Pass True, if the administrator can create channel posts, channels only pub can_post_messages: bool, /// Pass True, if the administrator can edit messages of other users and can pin messages, channels only @@ -29,14 +27,18 @@ impl_payload! { pub can_delete_messages: bool, /// Pass True, if the administrator can manage video chats, supergroups only pub can_manage_video_chats: bool, - /// Pass True, if the administrator can invite new users to the chat - pub can_invite_users: bool, /// Pass True, if the administrator can restrict, ban or unban chat members pub can_restrict_members: bool, - /// Pass True, if the administrator can pin messages, supergroups only - pub can_pin_messages: bool, /// Pass True, if the administrator can add new administrators with a subset of their own privileges or demote administrators that he has promoted, directly or indirectly (promoted by administrators that were appointed by him) pub can_promote_members: bool, + /// Pass True, if the administrator can change chat title, photo and other settings + pub can_change_info: bool, + /// Pass True, if the administrator can invite new users to the chat + pub can_invite_users: bool, + /// Pass True, if the administrator can pin messages, supergroups only + pub can_pin_messages: bool, + /// Pass True if the user is allowed to create, rename, close, and reopen forum topics, supergroups only + pub can_manage_topics: bool, } } } diff --git a/crates/teloxide-core/src/payloads/reopen_forum_topic.rs b/crates/teloxide-core/src/payloads/reopen_forum_topic.rs new file mode 100644 index 00000000..793fb5ac --- /dev/null +++ b/crates/teloxide-core/src/payloads/reopen_forum_topic.rs @@ -0,0 +1,18 @@ +//! Generated by `codegen_payloads`, do not edit by hand. + +use serde::Serialize; + +use crate::types::{Recipient, True}; + +impl_payload! { + /// Use this method to reopen a closed topic in a forum supergroup chat. The bot must be an administrator in the chat for this to work and must have the _can\_manage\_topics_ administrator rights, unless it is the creator of the topic. Returns True on success. + #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize)] + pub ReopenForumTopic (ReopenForumTopicSetters) => True { + required { + /// Unique identifier for the target chat or username of the target channel (in the format `@channelusername`) + pub chat_id: Recipient [into], + /// Unique identifier for the target message thread of the forum topic + pub message_thread_id: i32, + } + } +} diff --git a/crates/teloxide-core/src/payloads/send_animation.rs b/crates/teloxide-core/src/payloads/send_animation.rs index 118e1044..b6bc5b7f 100644 --- a/crates/teloxide-core/src/payloads/send_animation.rs +++ b/crates/teloxide-core/src/payloads/send_animation.rs @@ -22,6 +22,8 @@ impl_payload! { pub animation: InputFile, } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// Duration of the animation in seconds pub duration: u32, /// Animation width diff --git a/crates/teloxide-core/src/payloads/send_audio.rs b/crates/teloxide-core/src/payloads/send_audio.rs index 05b5c6ca..5d01eb8b 100644 --- a/crates/teloxide-core/src/payloads/send_audio.rs +++ b/crates/teloxide-core/src/payloads/send_audio.rs @@ -25,6 +25,8 @@ impl_payload! { pub audio: InputFile, } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// Audio caption, 0-1024 characters after entities parsing pub caption: String [into], /// Mode for parsing entities in the audio caption. See [formatting options] for more details. diff --git a/crates/teloxide-core/src/payloads/send_contact.rs b/crates/teloxide-core/src/payloads/send_contact.rs index d96b1faa..cc8a0c7a 100644 --- a/crates/teloxide-core/src/payloads/send_contact.rs +++ b/crates/teloxide-core/src/payloads/send_contact.rs @@ -19,6 +19,8 @@ impl_payload! { pub first_name: String [into], } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// Contact's last name pub last_name: String [into], /// Additional data about the contact in the form of a [vCard], 0-2048 bytes diff --git a/crates/teloxide-core/src/payloads/send_dice.rs b/crates/teloxide-core/src/payloads/send_dice.rs index 5a673cb9..53d1a54c 100644 --- a/crates/teloxide-core/src/payloads/send_dice.rs +++ b/crates/teloxide-core/src/payloads/send_dice.rs @@ -15,6 +15,8 @@ impl_payload! { pub chat_id: Recipient [into], } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// Emoji on which the dice throw animation is based. Currently, must be one of “🎲”, “🎯”, “🏀”, “⚽”, “🎳”, or “🎰”. Dice can have values 1-6 for “🎲”, “🎯” and “🎳”, values 1-5 for “🏀” and “⚽”, and values 1-64 for “🎰”. Defaults to “🎲” pub emoji: DiceEmoji, /// Sends the message [silently]. Users will receive a notification with no sound. diff --git a/crates/teloxide-core/src/payloads/send_document.rs b/crates/teloxide-core/src/payloads/send_document.rs index aaa684de..06fd9f3c 100644 --- a/crates/teloxide-core/src/payloads/send_document.rs +++ b/crates/teloxide-core/src/payloads/send_document.rs @@ -22,6 +22,8 @@ impl_payload! { pub document: InputFile, } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . [More info on Sending Files »] /// /// [More info on Sending Files »]: crate::types::InputFile diff --git a/crates/teloxide-core/src/payloads/send_game.rs b/crates/teloxide-core/src/payloads/send_game.rs index b348bfb3..be7144d0 100644 --- a/crates/teloxide-core/src/payloads/send_game.rs +++ b/crates/teloxide-core/src/payloads/send_game.rs @@ -17,6 +17,8 @@ impl_payload! { pub game_short_name: String [into], } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// Sends the message [silently]. Users will receive a notification with no sound. /// /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages diff --git a/crates/teloxide-core/src/payloads/send_invoice.rs b/crates/teloxide-core/src/payloads/send_invoice.rs index 85322d96..a888f166 100644 --- a/crates/teloxide-core/src/payloads/send_invoice.rs +++ b/crates/teloxide-core/src/payloads/send_invoice.rs @@ -30,6 +30,8 @@ impl_payload! { pub prices: Vec [collect], } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// The maximum accepted amount for tips in the smallest units of the currency (integer, **not** float/double). For example, for a maximum tip of `US$ 1.45` pass `max_tip_amount = 145`. See the exp parameter in [`currencies.json`], it shows the number of digits past the decimal point for each currency (2 for the majority of currencies). Defaults to 0 /// /// [`currencies.json`]: https://core.telegram.org/bots/payments/currencies.json diff --git a/crates/teloxide-core/src/payloads/send_location.rs b/crates/teloxide-core/src/payloads/send_location.rs index 69a84cee..68b70791 100644 --- a/crates/teloxide-core/src/payloads/send_location.rs +++ b/crates/teloxide-core/src/payloads/send_location.rs @@ -19,6 +19,8 @@ impl_payload! { pub longitude: f64, } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// The radius of uncertainty for the location, measured in meters; 0-1500 pub horizontal_accuracy: f64, /// Period in seconds for which the location will be updated (see [Live Locations], should be between 60 and 86400. diff --git a/crates/teloxide-core/src/payloads/send_media_group.rs b/crates/teloxide-core/src/payloads/send_media_group.rs index 9d2b14fa..edf224a9 100644 --- a/crates/teloxide-core/src/payloads/send_media_group.rs +++ b/crates/teloxide-core/src/payloads/send_media_group.rs @@ -17,6 +17,8 @@ impl_payload! { pub media: Vec [collect], } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// Sends the message [silently]. Users will receive a notification with no sound. /// /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages diff --git a/crates/teloxide-core/src/payloads/send_message.rs b/crates/teloxide-core/src/payloads/send_message.rs index 20899142..0b13dd23 100644 --- a/crates/teloxide-core/src/payloads/send_message.rs +++ b/crates/teloxide-core/src/payloads/send_message.rs @@ -17,6 +17,8 @@ impl_payload! { pub text: String [into], } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// Mode for parsing entities in the message text. See [formatting options] for more details. /// /// [formatting options]: https://core.telegram.org/bots/api#formatting-options diff --git a/crates/teloxide-core/src/payloads/send_photo.rs b/crates/teloxide-core/src/payloads/send_photo.rs index 50af80dd..77399f1c 100644 --- a/crates/teloxide-core/src/payloads/send_photo.rs +++ b/crates/teloxide-core/src/payloads/send_photo.rs @@ -22,6 +22,8 @@ impl_payload! { pub photo: InputFile, } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// Photo caption (may also be used when resending photos by _file\_id_), 0-1024 characters after entities parsing pub caption: String [into], /// Mode for parsing entities in the photo caption. See [formatting options] for more details. diff --git a/crates/teloxide-core/src/payloads/send_poll.rs b/crates/teloxide-core/src/payloads/send_poll.rs index bdc1f7f7..d346f61c 100644 --- a/crates/teloxide-core/src/payloads/send_poll.rs +++ b/crates/teloxide-core/src/payloads/send_poll.rs @@ -22,6 +22,8 @@ impl_payload! { pub options: Vec [collect], } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// True, if the poll needs to be anonymous, defaults to True pub is_anonymous: bool, /// Poll type, “quiz” or “regular”, defaults to “regular” diff --git a/crates/teloxide-core/src/payloads/send_sticker.rs b/crates/teloxide-core/src/payloads/send_sticker.rs index 2ebf8bdd..b677c5ef 100644 --- a/crates/teloxide-core/src/payloads/send_sticker.rs +++ b/crates/teloxide-core/src/payloads/send_sticker.rs @@ -20,6 +20,8 @@ impl_payload! { pub sticker: InputFile, } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// Sends the message [silently]. Users will receive a notification with no sound. /// /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages diff --git a/crates/teloxide-core/src/payloads/send_venue.rs b/crates/teloxide-core/src/payloads/send_venue.rs index d368aede..9b88da62 100644 --- a/crates/teloxide-core/src/payloads/send_venue.rs +++ b/crates/teloxide-core/src/payloads/send_venue.rs @@ -23,6 +23,8 @@ impl_payload! { pub address: String [into], } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// Foursquare identifier of the venue pub foursquare_id: String [into], /// Foursquare type of the venue, if known. (For example, “arts_entertainment/default”, “arts_entertainment/aquarium” or “food/icecream”.) diff --git a/crates/teloxide-core/src/payloads/send_video.rs b/crates/teloxide-core/src/payloads/send_video.rs index f267cbf3..9eb0f307 100644 --- a/crates/teloxide-core/src/payloads/send_video.rs +++ b/crates/teloxide-core/src/payloads/send_video.rs @@ -23,6 +23,8 @@ impl_payload! { pub video: InputFile, } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// Duration of the video in seconds pub duration: u32, /// Video width diff --git a/crates/teloxide-core/src/payloads/send_video_note.rs b/crates/teloxide-core/src/payloads/send_video_note.rs index 2c1e4484..f4406d48 100644 --- a/crates/teloxide-core/src/payloads/send_video_note.rs +++ b/crates/teloxide-core/src/payloads/send_video_note.rs @@ -21,6 +21,8 @@ impl_payload! { pub video_note: InputFile, } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// Duration of the video in seconds pub duration: u32, /// Video width and height, i.e. diameter of the video message diff --git a/crates/teloxide-core/src/payloads/send_voice.rs b/crates/teloxide-core/src/payloads/send_voice.rs index e1cbb888..5d854f52 100644 --- a/crates/teloxide-core/src/payloads/send_voice.rs +++ b/crates/teloxide-core/src/payloads/send_voice.rs @@ -24,6 +24,8 @@ impl_payload! { pub voice: InputFile, } optional { + /// Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + pub message_thread_id: i32, /// Voice message caption, 0-1024 characters after entities parsing pub caption: String [into], /// Mode for parsing entities in the voice message caption. See [formatting options] for more details. diff --git a/crates/teloxide-core/src/payloads/setters.rs b/crates/teloxide-core/src/payloads/setters.rs index d9e68c24..d111970f 100644 --- a/crates/teloxide-core/src/payloads/setters.rs +++ b/crates/teloxide-core/src/payloads/setters.rs @@ -5,27 +5,30 @@ pub use crate::payloads::{ AddStickerToSetSetters as _, AnswerCallbackQuerySetters as _, AnswerInlineQuerySetters as _, AnswerPreCheckoutQuerySetters as _, AnswerShippingQuerySetters as _, AnswerWebAppQuerySetters as _, ApproveChatJoinRequestSetters as _, BanChatMemberSetters as _, - BanChatSenderChatSetters as _, CloseSetters as _, CopyMessageSetters as _, - CreateChatInviteLinkSetters as _, CreateInvoiceLinkSetters as _, - CreateNewStickerSetSetters as _, DeclineChatJoinRequestSetters as _, - DeleteChatPhotoSetters as _, DeleteChatStickerSetSetters as _, DeleteMessageSetters as _, + BanChatSenderChatSetters as _, CloseForumTopicSetters as _, CloseSetters as _, + CopyMessageSetters as _, CreateChatInviteLinkSetters as _, CreateForumTopicSetters as _, + CreateInvoiceLinkSetters as _, CreateNewStickerSetSetters as _, + DeclineChatJoinRequestSetters as _, DeleteChatPhotoSetters as _, + DeleteChatStickerSetSetters as _, DeleteForumTopicSetters as _, DeleteMessageSetters as _, DeleteMyCommandsSetters as _, DeleteStickerFromSetSetters as _, DeleteWebhookSetters as _, - EditChatInviteLinkSetters as _, EditMessageCaptionInlineSetters as _, - EditMessageCaptionSetters as _, EditMessageLiveLocationInlineSetters as _, - EditMessageLiveLocationSetters as _, EditMessageMediaInlineSetters as _, - EditMessageMediaSetters as _, EditMessageReplyMarkupInlineSetters as _, - EditMessageReplyMarkupSetters as _, EditMessageTextInlineSetters as _, - EditMessageTextSetters as _, ExportChatInviteLinkSetters as _, ForwardMessageSetters as _, + EditChatInviteLinkSetters as _, EditForumTopicSetters as _, + EditMessageCaptionInlineSetters as _, EditMessageCaptionSetters as _, + EditMessageLiveLocationInlineSetters as _, EditMessageLiveLocationSetters as _, + EditMessageMediaInlineSetters as _, EditMessageMediaSetters as _, + EditMessageReplyMarkupInlineSetters as _, EditMessageReplyMarkupSetters as _, + EditMessageTextInlineSetters as _, EditMessageTextSetters as _, + ExportChatInviteLinkSetters as _, ForwardMessageSetters as _, GetChatAdministratorsSetters as _, GetChatMemberCountSetters as _, GetChatMemberSetters as _, GetChatMembersCountSetters as _, GetChatMenuButtonSetters as _, GetChatSetters as _, - GetCustomEmojiStickersSetters as _, GetFileSetters as _, GetGameHighScoresSetters as _, - GetMeSetters as _, GetMyCommandsSetters as _, GetMyDefaultAdministratorRightsSetters as _, - GetStickerSetSetters as _, GetUpdatesSetters as _, GetUserProfilePhotosSetters as _, - GetWebhookInfoSetters as _, KickChatMemberSetters as _, LeaveChatSetters as _, - LogOutSetters as _, PinChatMessageSetters as _, PromoteChatMemberSetters as _, - RestrictChatMemberSetters as _, RevokeChatInviteLinkSetters as _, SendAnimationSetters as _, - SendAudioSetters as _, SendChatActionSetters as _, SendContactSetters as _, - SendDiceSetters as _, SendDocumentSetters as _, SendGameSetters as _, SendInvoiceSetters as _, + GetCustomEmojiStickersSetters as _, GetFileSetters as _, GetForumTopicIconStickersSetters as _, + GetGameHighScoresSetters as _, GetMeSetters as _, GetMyCommandsSetters as _, + GetMyDefaultAdministratorRightsSetters as _, GetStickerSetSetters as _, GetUpdatesSetters as _, + GetUserProfilePhotosSetters as _, GetWebhookInfoSetters as _, KickChatMemberSetters as _, + LeaveChatSetters as _, LogOutSetters as _, PinChatMessageSetters as _, + PromoteChatMemberSetters as _, ReopenForumTopicSetters as _, RestrictChatMemberSetters as _, + RevokeChatInviteLinkSetters as _, SendAnimationSetters as _, SendAudioSetters as _, + SendChatActionSetters as _, SendContactSetters as _, SendDiceSetters as _, + SendDocumentSetters as _, SendGameSetters as _, SendInvoiceSetters as _, SendLocationSetters as _, SendMediaGroupSetters as _, SendMessageSetters as _, SendPhotoSetters as _, SendPollSetters as _, SendStickerSetters as _, SendVenueSetters as _, SendVideoNoteSetters as _, SendVideoSetters as _, SendVoiceSetters as _, @@ -37,5 +40,6 @@ pub use crate::payloads::{ SetStickerPositionInSetSetters as _, SetStickerSetThumbSetters as _, SetWebhookSetters as _, StopMessageLiveLocationInlineSetters as _, StopMessageLiveLocationSetters as _, StopPollSetters as _, UnbanChatMemberSetters as _, UnbanChatSenderChatSetters as _, - UnpinAllChatMessagesSetters as _, UnpinChatMessageSetters as _, UploadStickerFileSetters as _, + UnpinAllChatMessagesSetters as _, UnpinAllForumTopicMessagesSetters as _, + UnpinChatMessageSetters as _, UploadStickerFileSetters as _, }; diff --git a/crates/teloxide-core/src/payloads/unpin_all_forum_topic_messages.rs b/crates/teloxide-core/src/payloads/unpin_all_forum_topic_messages.rs new file mode 100644 index 00000000..6b0cc7a4 --- /dev/null +++ b/crates/teloxide-core/src/payloads/unpin_all_forum_topic_messages.rs @@ -0,0 +1,18 @@ +//! Generated by `codegen_payloads`, do not edit by hand. + +use serde::Serialize; + +use crate::types::{Recipient, True}; + +impl_payload! { + /// Use this method to clear the list of pinned messages in a forum topic. The bot must be an administrator in the chat for this to work and must have the _can\_pin\_messages_ administrator right in the supergroup. Returns True on success. + #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize)] + pub UnpinAllForumTopicMessages (UnpinAllForumTopicMessagesSetters) => True { + required { + /// Unique identifier for the target chat or username of the target channel (in the format `@channelusername`) + pub chat_id: Recipient [into], + /// Unique identifier for the target message thread of the forum topic + pub message_thread_id: i32, + } + } +} diff --git a/crates/teloxide-core/src/requests/requester.rs b/crates/teloxide-core/src/requests/requester.rs index f4a29663..6f93f79e 100644 --- a/crates/teloxide-core/src/requests/requester.rs +++ b/crates/teloxide-core/src/requests/requester.rs @@ -659,6 +659,73 @@ pub trait Requester { where C: Into; + type GetForumTopicIconStickers: Request; + + /// For Telegram documentation see [`GetForumTopicIconStickers`]. + fn get_forum_topic_icon_stickers(&self) -> Self::GetForumTopicIconStickers; + + type CreateForumTopic: Request; + + /// For Telegram documentation see [`CreateForumTopic`]. + fn create_forum_topic( + &self, + chat_id: C, + name: N, + icon_color: u32, + icon_custom_emoji_id: I, + ) -> Self::CreateForumTopic + where + C: Into, + N: Into, + I: Into; + + type EditForumTopic: Request; + + /// For Telegram documentation see [`EditForumTopic`]. + fn edit_forum_topic( + &self, + chat_id: C, + message_thread_id: i32, + name: N, + icon_custom_emoji_id: I, + ) -> Self::EditForumTopic + where + C: Into, + N: Into, + I: Into; + + type CloseForumTopic: Request; + + /// For Telegram documentation see [`CloseForumTopic`]. + fn close_forum_topic(&self, chat_id: C, message_thread_id: i32) -> Self::CloseForumTopic + where + C: Into; + + type ReopenForumTopic: Request; + + /// For Telegram documentation see [`ReopenForumTopic`]. + fn reopen_forum_topic(&self, chat_id: C, message_thread_id: i32) -> Self::ReopenForumTopic + where + C: Into; + + type DeleteForumTopic: Request; + + /// For Telegram documentation see [`DeleteForumTopic`]. + fn delete_forum_topic(&self, chat_id: C, message_thread_id: i32) -> Self::DeleteForumTopic + where + C: Into; + + type UnpinAllForumTopicMessages: Request; + + /// For Telegram documentation see [`UnpinAllForumTopicMessages`]. + fn unpin_all_forum_topic_messages( + &self, + chat_id: C, + message_thread_id: i32, + ) -> Self::UnpinAllForumTopicMessages + where + C: Into; + type AnswerCallbackQuery: Request; /// For Telegram documentation see [`AnswerCallbackQuery`]. @@ -1103,6 +1170,13 @@ macro_rules! forward_all { get_chat_member, set_chat_sticker_set, delete_chat_sticker_set, + get_forum_topic_icon_stickers, + create_forum_topic, + edit_forum_topic, + close_forum_topic, + reopen_forum_topic, + delete_forum_topic, + unpin_all_forum_topic_messages, answer_callback_query, set_my_commands, get_my_commands, diff --git a/crates/teloxide-core/src/types.rs b/crates/teloxide-core/src/types.rs index 0b09f7c0..533f7afc 100644 --- a/crates/teloxide-core/src/types.rs +++ b/crates/teloxide-core/src/types.rs @@ -27,6 +27,10 @@ pub use encrypted_credentials::*; pub use encrypted_passport_element::*; pub use file::*; pub use force_reply::*; +pub use forum_topic::*; +pub use forum_topic_closed::*; +pub use forum_topic_created::*; +pub use forum_topic_reopened::*; pub use game::*; pub use game_high_score::*; pub use inline_keyboard_button::*; @@ -86,7 +90,6 @@ pub use reply_keyboard_remove::*; pub use reply_markup::*; pub use response_parameters::*; pub use sent_web_app_message::*; -use serde::Serialize; pub use shipping_address::*; pub use shipping_option::*; pub use shipping_query::*; @@ -136,6 +139,10 @@ mod dice_emoji; mod document; mod file; mod force_reply; +mod forum_topic; +mod forum_topic_closed; +mod forum_topic_created; +mod forum_topic_reopened; mod game; mod game_high_score; mod inline_keyboard_button; @@ -239,6 +246,8 @@ pub use chat_id::*; pub use recipient::*; pub use user_id::*; +use serde::Serialize; + /// Converts an `i64` timestump to a `choro::DateTime`, producing serde error /// for invalid timestumps pub(crate) fn serde_timestamp( @@ -420,3 +429,49 @@ where { this.map(|MessageId(id)| id).serialize(serializer) } + +pub(crate) mod serde_rgb { + use serde::{de::Visitor, Deserializer, Serializer}; + + pub fn serialize(&this: &[u8; 3], s: S) -> Result { + s.serialize_u32(to_u32(this)) + } + + pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<[u8; 3], D::Error> { + struct V; + + impl Visitor<'_> for V { + type Value = [u8; 3]; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("an integer represeting an RGB color") + } + + fn visit_u32(self, v: u32) -> Result + where + E: serde::de::Error, + { + Ok(from_u32(v)) + } + } + d.deserialize_u32(V) + } + + fn to_u32([r, g, b]: [u8; 3]) -> u32 { + u32::from_be_bytes([0, r, g, b]) + } + + fn from_u32(rgb: u32) -> [u8; 3] { + let [_, r, g, b] = rgb.to_be_bytes(); + [r, g, b] + } + + #[test] + fn bytes() { + assert_eq!(to_u32([0xAA, 0xBB, 0xCC]), 0x00AABBCC); + assert_eq!(from_u32(0x00AABBCC), [0xAA, 0xBB, 0xCC]); + } + + #[test] + fn json() {} +} diff --git a/crates/teloxide-core/src/types/chat.rs b/crates/teloxide-core/src/types/chat.rs index 96d470ae..9c9e31e6 100644 --- a/crates/teloxide-core/src/types/chat.rs +++ b/crates/teloxide-core/src/types/chat.rs @@ -88,6 +88,13 @@ pub struct ChatPrivate { /// A last name of the other party in a private chat. pub last_name: Option, + /// Custom emoji identifier of emoji status of the other party in a private + /// chat. Returned only in [`GetChat`]. + /// + /// [`GetChat`]: crate::payloads::GetChat + // FIXME: CustomEmojiId + pub emoji_status_custom_emoji_id: Option, + /// Bio of the other party in a private chat. Returned only in [`GetChat`]. /// /// [`GetChat`]: crate::payloads::GetChat @@ -148,6 +155,16 @@ pub struct PublicChatSupergroup { /// available. pub username: Option, + /// If non-empty, the list of all active chat usernames; for private chats, + /// supergroups and channels. Returned only from [`GetChat`]. + /// + /// [`GetChat`]: crate::payloads::GetChat + pub active_usernames: Option>, + + /// `true`, if the supergroup chat is a forum (has topics enabled). + #[serde(default)] + pub is_forum: bool, + /// For supergroups, name of group sticker set. Returned only from /// [`GetChat`]. /// @@ -485,6 +502,7 @@ mod serde_helper { bio: Option, has_private_forwards: Option, has_restricted_voice_and_video_messages: Option, + emoji_status_custom_emoji_id: Option, } impl From for super::ChatPrivate { @@ -497,6 +515,7 @@ mod serde_helper { bio, has_private_forwards, has_restricted_voice_and_video_messages, + emoji_status_custom_emoji_id, }: ChatPrivate, ) -> Self { Self { @@ -506,6 +525,7 @@ mod serde_helper { bio, has_private_forwards, has_restricted_voice_and_video_messages, + emoji_status_custom_emoji_id, } } } @@ -519,6 +539,7 @@ mod serde_helper { bio, has_private_forwards, has_restricted_voice_and_video_messages, + emoji_status_custom_emoji_id, }: super::ChatPrivate, ) -> Self { Self { @@ -529,6 +550,7 @@ mod serde_helper { bio, has_private_forwards, has_restricted_voice_and_video_messages, + emoji_status_custom_emoji_id, } } } @@ -574,6 +596,7 @@ mod tests { bio: None, has_private_forwards: None, has_restricted_voice_and_video_messages: None, + emoji_status_custom_emoji_id: None }), photo: None, pinned_message: None, @@ -595,6 +618,7 @@ mod tests { bio: None, has_private_forwards: None, has_restricted_voice_and_video_messages: None, + emoji_status_custom_emoji_id: None, }), photo: None, pinned_message: None, diff --git a/crates/teloxide-core/src/types/chat_administrator_rights.rs b/crates/teloxide-core/src/types/chat_administrator_rights.rs index 047f70f5..b00da3d7 100644 --- a/crates/teloxide-core/src/types/chat_administrator_rights.rs +++ b/crates/teloxide-core/src/types/chat_administrator_rights.rs @@ -45,4 +45,8 @@ pub struct ChatAdministratorRights { /// `true`, if the user is allowed to pin messages; groups and /// supergroups only pub can_pin_messages: Option, + + /// `true`, if the user is allowed to create, rename, close, and reopen + /// forum topics; supergroups only + pub can_manage_topics: Option, } diff --git a/crates/teloxide-core/src/types/chat_member.rs b/crates/teloxide-core/src/types/chat_member.rs index d4af17ea..59cb4f5b 100644 --- a/crates/teloxide-core/src/types/chat_member.rs +++ b/crates/teloxide-core/src/types/chat_member.rs @@ -87,6 +87,10 @@ pub struct Administrator { /// `true` if the administrator can pin messages, supergroups only. pub can_pin_messages: Option, + /// `true`, if the user is allowed to create, rename, close, and reopen + /// forum topics; supergroups only + pub can_manage_topics: Option, + /// `true` if the administrator can add new administrators with a subset of /// his own privileges or demote administrators that he has promoted, /// directly or indirectly (promoted by administrators that were appointed @@ -130,6 +134,10 @@ pub struct Restricted { /// `true` if the user is allowed to pin messages. pub can_pin_messages: bool, + /// `true`, if the user is allowed to create, rename, close, and reopen + /// forum topics + pub can_manage_topics: bool, + /// `true` if the user is allowed to send polls. pub can_send_polls: bool, } @@ -514,6 +522,27 @@ impl ChatMemberKind { } } + /// Returns `true` if the user is allowed to manage topics. + /// + /// I.e. returns `true` if the user + /// - is the owner of the chat (even if the chat is not a supergroup) + /// - is an administrator in the given chat and has the + /// [`Administrator::can_manage_topics`] privilege. + /// - is restricted, but does have [`Restricted::can_manage_topics`] + /// privilege + /// Returns `false` otherwise. + #[must_use] + pub fn can_manage_topics(&self) -> bool { + match self { + ChatMemberKind::Owner(_) => true, + ChatMemberKind::Administrator(Administrator { can_manage_topics, .. }) => { + can_manage_topics.unwrap_or_default() + } + ChatMemberKind::Restricted(Restricted { can_manage_topics, .. }) => *can_manage_topics, + ChatMemberKind::Member | ChatMemberKind::Left | ChatMemberKind::Banned(_) => false, + } + } + /// Returns `true` if the user can add new administrators with a subset of /// his own privileges or demote administrators that he has promoted, /// directly or indirectly (promoted by administrators that were appointed @@ -780,6 +809,7 @@ mod tests { can_restrict_members: true, can_pin_messages: Some(true), can_promote_members: true, + can_manage_topics: None, }), }; let actual = serde_json::from_str::(json).unwrap(); diff --git a/crates/teloxide-core/src/types/chat_permissions.rs b/crates/teloxide-core/src/types/chat_permissions.rs index 77585d70..2fe560c4 100644 --- a/crates/teloxide-core/src/types/chat_permissions.rs +++ b/crates/teloxide-core/src/types/chat_permissions.rs @@ -46,7 +46,7 @@ bitflags::bitflags! { /// ``` #[derive(Serialize, Deserialize)] #[serde(from = "ChatPermissionsRaw", into = "ChatPermissionsRaw")] - pub struct ChatPermissions: u8 { + pub struct ChatPermissions: u16 { /// Set if the user is allowed to send text messages, contacts, /// locations and venues. const SEND_MESSAGES = 1; @@ -78,9 +78,14 @@ bitflags::bitflags! { /// Set if the user is allowed to pin messages. Ignored in public /// supergroups. const PIN_MESSAGES = (1 << 7); + + /// Set if the user is allowed to create, rename, close, and reopen forum topics. + const MANAGE_TOPICS = (1 << 8); } } +// FIXME: add `can_*` methods for convinience + /// Helper for (de)serialization #[derive(Serialize, Deserialize)] struct ChatPermissionsRaw { @@ -107,6 +112,13 @@ struct ChatPermissionsRaw { #[serde(default, skip_serializing_if = "Not::not")] can_pin_messages: bool, + + // HACK: do not `skip_serializing_if = "Not::not"`, from tg docs: + // > If omitted defaults to the value of `can_pin_messages` + // but we don't have two different values for "absent" and "false"... + // or did they mean that `can_pin_messages` implies `can_manage_topics`?.. + #[serde(default)] + can_manage_topics: bool, } impl From for ChatPermissionsRaw { @@ -120,6 +132,7 @@ impl From for ChatPermissionsRaw { can_change_info: this.contains(ChatPermissions::CHANGE_INFO), can_invite_users: this.contains(ChatPermissions::INVITE_USERS), can_pin_messages: this.contains(ChatPermissions::PIN_MESSAGES), + can_manage_topics: this.contains(ChatPermissions::MANAGE_TOPICS), } } } @@ -135,6 +148,7 @@ impl From for ChatPermissions { can_change_info, can_invite_users, can_pin_messages, + can_manage_topics, }: ChatPermissionsRaw, ) -> Self { let mut this = Self::empty(); @@ -163,6 +177,10 @@ impl From for ChatPermissions { if can_pin_messages { this |= Self::PIN_MESSAGES; } + // FIXME: should we do `|| can_pin_messages` here? (the same tg doc weirdness) + if can_manage_topics { + this |= Self::MANAGE_TOPICS + } this } @@ -175,8 +193,7 @@ mod tests { #[test] fn serialization() { let permissions = ChatPermissions::SEND_MEDIA_MESSAGES | ChatPermissions::PIN_MESSAGES; - let expected = - r#"{"can_send_messages":true,"can_send_media_messages":true,"can_pin_messages":true}"#; + let expected = r#"{"can_send_messages":true,"can_send_media_messages":true,"can_pin_messages":true,"can_manage_topics":false}"#; let actual = serde_json::to_string(&permissions).unwrap(); assert_eq!(expected, actual); } diff --git a/crates/teloxide-core/src/types/forum_topic.rs b/crates/teloxide-core/src/types/forum_topic.rs new file mode 100644 index 00000000..60c651b7 --- /dev/null +++ b/crates/teloxide-core/src/types/forum_topic.rs @@ -0,0 +1,24 @@ +use serde::{Deserialize, Serialize}; + +/// This object represents a forum topic. +/// +/// [The official docs](https://core.telegram.org/bots/api#forumtopiccreated). +#[serde_with_macros::skip_serializing_none] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] +pub struct ForumTopic { + /// Unique identifier of the forum topic + // FIXME: MessageThreadId or something + pub message_thread_id: i32, + + /// Name of the topic. + pub name: String, + + /// Color of the topic icon in RGB format. + // FIXME: use/add a specialized rgb color type? + #[serde(with = "crate::types::serde_rgb")] + pub icon_color: [u8; 3], + + /// Unique identifier of the custom emoji shown as the topic icon. + // FIXME: CustomEmojiId + pub icon_custom_emoji_id: Option, +} diff --git a/crates/teloxide-core/src/types/forum_topic_closed.rs b/crates/teloxide-core/src/types/forum_topic_closed.rs new file mode 100644 index 00000000..b3d45cf5 --- /dev/null +++ b/crates/teloxide-core/src/types/forum_topic_closed.rs @@ -0,0 +1,9 @@ +use serde::{Deserialize, Serialize}; + +/// This object represents a service message about a forum topic closed in the +/// chat. Currently holds no information. +/// +/// [The official docs](https://core.telegram.org/bots/api#forumtopiccreated). +#[serde_with_macros::skip_serializing_none] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] +pub struct ForumTopicClosed; diff --git a/crates/teloxide-core/src/types/forum_topic_created.rs b/crates/teloxide-core/src/types/forum_topic_created.rs new file mode 100644 index 00000000..cf4a91b6 --- /dev/null +++ b/crates/teloxide-core/src/types/forum_topic_created.rs @@ -0,0 +1,21 @@ +use serde::{Deserialize, Serialize}; + +/// This object represents a service message about a new forum topic created in +/// the chat. +/// +/// [The official docs](https://core.telegram.org/bots/api#forumtopiccreated). +#[serde_with_macros::skip_serializing_none] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] +pub struct ForumTopicCreated { + /// Name of the topic. + pub name: String, + + /// Color of the topic icon in RGB format. + // FIXME: use/add a specialized rgb color type? + #[serde(with = "crate::types::serde_rgb")] + pub icon_color: [u8; 3], + + /// Unique identifier of the custom emoji shown as the topic icon. + // FIXME: CustomEmojiId + pub icon_custom_emoji_id: Option, +} diff --git a/crates/teloxide-core/src/types/forum_topic_reopened.rs b/crates/teloxide-core/src/types/forum_topic_reopened.rs new file mode 100644 index 00000000..88107186 --- /dev/null +++ b/crates/teloxide-core/src/types/forum_topic_reopened.rs @@ -0,0 +1,9 @@ +use serde::{Deserialize, Serialize}; + +/// This object represents a service message about a forum topic reopened in the +/// chat. Currently holds no information. +/// +/// [The official docs](https://core.telegram.org/bots/api#forumtopiccreated). +#[serde_with_macros::skip_serializing_none] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] +pub struct ForumTopicReopened; diff --git a/crates/teloxide-core/src/types/message.rs b/crates/teloxide-core/src/types/message.rs index d0ff1510..00927091 100644 --- a/crates/teloxide-core/src/types/message.rs +++ b/crates/teloxide-core/src/types/message.rs @@ -5,11 +5,12 @@ use serde::{Deserialize, Serialize}; use url::Url; use crate::types::{ - Animation, Audio, BareChatId, Chat, ChatId, Contact, Dice, Document, Game, - InlineKeyboardMarkup, Invoice, Location, MessageAutoDeleteTimerChanged, MessageEntity, - MessageEntityRef, MessageId, PassportData, PhotoSize, Poll, ProximityAlertTriggered, Sticker, - SuccessfulPayment, True, User, Venue, Video, VideoChatEnded, VideoChatParticipantsInvited, - VideoChatScheduled, VideoChatStarted, VideoNote, Voice, WebAppData, + Animation, Audio, BareChatId, Chat, ChatId, Contact, Dice, Document, ForumTopicClosed, + ForumTopicCreated, ForumTopicReopened, Game, InlineKeyboardMarkup, Invoice, Location, + MessageAutoDeleteTimerChanged, MessageEntity, MessageEntityRef, MessageId, PassportData, + PhotoSize, Poll, ProximityAlertTriggered, Sticker, SuccessfulPayment, True, User, Venue, Video, + VideoChatEnded, VideoChatParticipantsInvited, VideoChatScheduled, VideoChatStarted, VideoNote, + Voice, WebAppData, }; /// This object represents a message. @@ -21,6 +22,11 @@ pub struct Message { #[serde(flatten)] pub id: MessageId, + /// Unique identifier of a message thread to which the message belongs; for + /// supergroups only. + // FIXME: MessageThreadId or such + pub thread_id: Option, + /// Date the message was sent in Unix time. #[serde(with = "crate::types::serde_date_from_unix_timestamp")] pub date: DateTime, @@ -55,6 +61,9 @@ pub enum MessageKind { PassportData(MessagePassportData), Dice(MessageDice), ProximityAlertTriggered(MessageProximityAlertTriggered), + ForumTopicCreated(ForumTopicCreated), + ForumTopicClosed(ForumTopicClosed), + ForumTopicReopened(ForumTopicReopened), VideoChatScheduled(MessageVideoChatScheduled), VideoChatStarted(MessageVideoChatStarted), VideoChatEnded(MessageVideoChatEnded), @@ -98,6 +107,10 @@ pub struct MessageCommon { /// represented as ordinary `url` buttons. pub reply_markup: Option, + /// `true`, if the message is sent to a forum topic. + #[serde(default)] + pub is_topic_message: bool, + /// `true`, if the message is a channel post that was automatically /// forwarded to the connected discussion group. #[serde(default)] @@ -493,6 +506,24 @@ pub struct MessageProximityAlertTriggered { pub proximity_alert_triggered: ProximityAlertTriggered, } +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MessageForumTopicCreated { + /// Service message: forum topic created. + pub forum_topic_created: ForumTopicCreated, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MessageForumTopicClosed { + /// Service message: forum topic closed. + pub forum_topic_closed: ForumTopicClosed, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MessageForumTopicReopened { + /// Service message: forum topic reopened. + pub forum_topic_reopened: ForumTopicReopened, +} + #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct MessageVideoChatScheduled { /// Service message: video chat scheduled @@ -1543,6 +1574,8 @@ mod tests { location: None, join_by_request: None, join_to_send_messages: None, + active_usernames: None, + is_forum: false, }), description: None, invite_link: None, diff --git a/crates/teloxide-core/src/types/update.rs b/crates/teloxide-core/src/types/update.rs index d34c3798..df8f7cd6 100644 --- a/crates/teloxide-core/src/types/update.rs +++ b/crates/teloxide-core/src/types/update.rs @@ -332,6 +332,7 @@ mod test { kind: UpdateKind::Message(Message { via_bot: None, id: MessageId(6557), + thread_id: None, date, chat: Chat { id: ChatId(218_485_655), @@ -342,6 +343,7 @@ mod test { bio: None, has_private_forwards: None, has_restricted_voice_and_video_messages: None, + emoji_status_custom_emoji_id: None, }), photo: None, pinned_message: None, @@ -368,6 +370,7 @@ mod test { reply_markup: None, sender_chat: None, author_signature: None, + is_topic_message: false, is_automatic_forward: false, has_protected_content: false, }),