Merge branch 'dev' into conversion_traits_for_parse_mode

This commit is contained in:
Waffle Lapkin 2020-01-01 03:28:08 +03:00 committed by GitHub
commit 585c161511
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 306 additions and 50 deletions

View file

@ -18,7 +18,8 @@ use crate::{
RestrictChatMember, SendAnimation, SendAudio, SendChatAction, RestrictChatMember, SendAnimation, SendAudio, SendChatAction,
SendContact, SendDocument, SendGame, SendInvoice, SendLocation, SendContact, SendDocument, SendGame, SendInvoice, SendLocation,
SendMediaGroup, SendMessage, SendPhoto, SendPoll, SendSticker, SendMediaGroup, SendMessage, SendPhoto, SendPoll, SendSticker,
SendVenue, SendVideo, SendVideoNote, SendVoice, SetChatDescription, SendVenue, SendVideo, SendVideoNote, SendVoice,
SetChatAdministratorCustomTitle, SetChatDescription,
SetChatPermission, SetChatPhoto, SetChatStickerSet, SetChatTitle, SetChatPermission, SetChatPhoto, SetChatStickerSet, SetChatTitle,
SetGameScore, SetGameScoreInline, SetStickerPositionInSet, SetGameScore, SetGameScoreInline, SetStickerPositionInSet,
SetWebhook, StopMessageLiveLocation, StopMessageLiveLocationInline, SetWebhook, StopMessageLiveLocation, StopMessageLiveLocationInline,
@ -1150,4 +1151,28 @@ impl Bot {
GetGameHighScore::new(chat_id, message_id, user_id), GetGameHighScore::new(chat_id, message_id, user_id),
) )
} }
/// For tg-method documentation see [`SetChatAdministratorCustomTitle`]
///
/// [`SetChatAdministratorCustomTitle`]:
/// crate::requests::payloads::SetChatAdministratorCustomTitle
pub fn set_chat_administrator_custom_title<C, CT>(
&self,
chat_id: C,
user_id: i32,
custom_title: CT,
) -> json::Request<SetChatAdministratorCustomTitle>
where
C: Into<ChatId>,
CT: Into<String>,
{
json::Request::new(
self,
SetChatAdministratorCustomTitle::new(
chat_id,
user_id,
custom_title,
),
)
}
} }

View file

@ -28,7 +28,7 @@ type FiltersWithHandlers<'a, T, E> = Vec<FilterWithHandler<'a, T, E>>;
/// acts: /// acts:
/// ///
/// <div align="center"> /// <div align="center">
/// <img src="https://github.com/teloxide/teloxide/blob/dev/media/FILTER_DP_FLOWCHART.png" width="700" /> /// <img src="https://raw.githubusercontent.com/teloxide/teloxide/dev/media/FILTER_DP_FLOWCHART.png" width="700" />
/// </div> /// </div>
/// ///
/// ## Examples /// ## Examples
@ -69,8 +69,10 @@ type FiltersWithHandlers<'a, T, E> = Vec<FilterWithHandler<'a, T, E>>;
/// ``` /// ```
/// ///
/// [`std::fmt::Debug`]: std::fmt::Debug /// [`std::fmt::Debug`]: std::fmt::Debug
/// [updater]: crate::dispatching::updater
/// [`.dispatch(updater)`]: FilterDispatcher::dispatch /// [`.dispatch(updater)`]: FilterDispatcher::dispatch
/// [`ErrorHandler`]: crate::dispatching::error_handlers::ErrorHandler
/// [`Updater`]: crate::dispatching::updaters::Updater
/// [`Handler`]: crate::dispatching::Handler
pub struct FilterDispatcher<'a, E, Eh> { pub struct FilterDispatcher<'a, E, Eh> {
message_handlers: FiltersWithHandlers<'a, Message, E>, message_handlers: FiltersWithHandlers<'a, Message, E>,
edited_message_handlers: FiltersWithHandlers<'a, Message, E>, edited_message_handlers: FiltersWithHandlers<'a, Message, E>,

View file

@ -0,0 +1 @@
pub mod filter;

View file

@ -1,13 +1,13 @@
//! Update dispatching. //! Update dispatching.
mod dispatchers;
pub mod error_handlers; pub mod error_handlers;
mod filter_dp;
pub mod filters; pub mod filters;
mod handler; mod handler;
pub mod updaters; pub mod updaters;
pub use dispatchers::filter::FilterDispatcher;
pub use error_handlers::ErrorHandler; pub use error_handlers::ErrorHandler;
pub use filter_dp::FilterDispatcher;
pub use filters::Filter; pub use filters::Filter;
pub use handler::Handler; pub use handler::Handler;
pub use updaters::Updater; pub use updaters::Updater;

View file

@ -123,7 +123,9 @@ impl IntoFormValue for str {
impl IntoFormValue for ParseMode { impl IntoFormValue for ParseMode {
fn into_form_value(&self) -> Option<FormValue> { fn into_form_value(&self) -> Option<FormValue> {
let string = match self { let string = match self {
ParseMode::MarkdownV2 => String::from("MarkdownV2"),
ParseMode::HTML => String::from("HTML"), ParseMode::HTML => String::from("HTML"),
#[allow(deprecated)]
ParseMode::Markdown => String::from("Markdown"), ParseMode::Markdown => String::from("Markdown"),
}; };
Some(FormValue::Str(string)) Some(FormValue::Str(string))

View file

@ -115,6 +115,7 @@ pub mod payloads {
mod set_game_score; mod set_game_score;
mod get_game_high_scores; mod get_game_high_scores;
mod get_game_high_scores_inline; mod get_game_high_scores_inline;
mod set_chat_administrator_custom_title;
pub use { pub use {
get_updates::{GetUpdates, AllowedUpdate}, get_updates::{GetUpdates, AllowedUpdate},
@ -189,5 +190,6 @@ pub mod payloads {
set_game_score::SetGameScore, set_game_score::SetGameScore,
get_game_high_scores_inline::GetGameHighScoreInline, get_game_high_scores_inline::GetGameHighScoreInline,
get_game_high_scores::GetGameHighScore, get_game_high_scores::GetGameHighScore,
set_chat_administrator_custom_title::SetChatAdministratorCustomTitle,
}; };
} }

View file

@ -0,0 +1,76 @@
use serde::{Deserialize, Serialize};
use crate::{
requests::{dynamic, json, Method},
types::{True, ChatId},
};
/// Use this method to set a custom title for an administrator in a supergroup
/// promoted by the bot.
#[serde_with_macros::skip_serializing_none]
#[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize, Serialize)]
pub struct SetChatAdministratorCustomTitle {
/// Unique identifier for the target chat or username of the target
/// supergroup (in the format `@supergroupusername`)
pub chat_id: ChatId,
/// Unique identifier of the target user
pub user_id: i32,
/// New custom title for the administrator; 0-16 characters, emoji are not
/// allowed
pub custom_title: String,
}
impl Method for SetChatAdministratorCustomTitle {
type Output = True;
const NAME: &'static str = "setChatAdministratorCustomTitle";
}
impl json::Payload for SetChatAdministratorCustomTitle {}
impl dynamic::Payload for SetChatAdministratorCustomTitle {
fn kind(&self) -> dynamic::Kind {
dynamic::Kind::Json(serde_json::to_string(self).unwrap())
}
}
impl SetChatAdministratorCustomTitle {
pub fn new<C, CT>(chat_id: C, user_id: i32, custom_title: CT) -> Self
where
C: Into<ChatId>,
CT: Into<String>,
{
let chat_id = chat_id.into();
let custom_title = custom_title.into();
Self {
chat_id,
user_id,
custom_title,
}
}
}
impl json::Request<'_, SetChatAdministratorCustomTitle> {
pub fn chat_id<T>(mut self, val: T) -> Self
where
T: Into<ChatId>,
{
self.payload.chat_id = val.into();
self
}
pub fn user_id(mut self, val: i32) -> Self {
self.payload.user_id = val;
self
}
pub fn custom_title<T>(mut self, val: T) -> Self
where
T: Into<String>,
{
self.payload.custom_title = val.into();
self
}
}

View file

@ -12,6 +12,11 @@ pub struct Animation {
/// An identifier for this file. /// An identifier for this file.
pub file_id: String, pub file_id: String,
/// Unique identifier for this file, which is supposed to be the same over
/// time and for different bots. Can't be used to download or reuse the
/// file.
pub file_unique_id: String,
/// A video width as defined by a sender. /// A video width as defined by a sender.
pub width: u32, pub width: u32,
@ -42,11 +47,13 @@ mod tests {
fn deserialize() { fn deserialize() {
let json = r#"{ let json = r#"{
"file_id":"id", "file_id":"id",
"file_unique_id":"",
"width":320, "width":320,
"height":320, "height":320,
"duration":59, "duration":59,
"thumb":{ "thumb":{
"file_id":"id", "file_id":"id",
"file_unique_id":"",
"width":320, "width":320,
"height":320, "height":320,
"file_size":3452 "file_size":3452
@ -56,11 +63,13 @@ mod tests {
"file_size":6500}"#; "file_size":6500}"#;
let expected = Animation { let expected = Animation {
file_id: "id".to_string(), file_id: "id".to_string(),
file_unique_id: "".to_string(),
width: 320, width: 320,
height: 320, height: 320,
duration: 59, duration: 59,
thumb: Some(PhotoSize { thumb: Some(PhotoSize {
file_id: "id".to_string(), file_id: "id".to_string(),
file_unique_id: "".to_string(),
width: 320, width: 320,
height: 320, height: 320,
file_size: Some(3452), file_size: Some(3452),

View file

@ -12,6 +12,11 @@ pub struct Audio {
/// An identifier for this file. /// An identifier for this file.
pub file_id: String, pub file_id: String,
/// Unique identifier for this file, which is supposed to be the same over
/// time and for different bots. Can't be used to download or reuse the
/// file.
pub file_unique_id: String,
/// A duration of the audio in seconds as defined by a sender. /// A duration of the audio in seconds as defined by a sender.
pub duration: u32, pub duration: u32,
@ -39,6 +44,7 @@ mod tests {
fn deserialize() { fn deserialize() {
let json = r#"{ let json = r#"{
"file_id":"id", "file_id":"id",
"file_unique_id":"",
"duration":60, "duration":60,
"performer":"Performer", "performer":"Performer",
"title":"Title", "title":"Title",
@ -46,6 +52,7 @@ mod tests {
"file_size":123456, "file_size":123456,
"thumb":{ "thumb":{
"file_id":"id", "file_id":"id",
"file_unique_id":"",
"width":320, "width":320,
"height":320, "height":320,
"file_size":3452 "file_size":3452
@ -53,6 +60,7 @@ mod tests {
}"#; }"#;
let expected = Audio { let expected = Audio {
file_id: "id".to_string(), file_id: "id".to_string(),
file_unique_id: "".to_string(),
duration: 60, duration: 60,
performer: Some("Performer".to_string()), performer: Some("Performer".to_string()),
title: Some("Title".to_string()), title: Some("Title".to_string()),
@ -60,6 +68,7 @@ mod tests {
file_size: Some(123_456), file_size: Some(123_456),
thumb: Some(PhotoSize { thumb: Some(PhotoSize {
file_id: "id".to_string(), file_id: "id".to_string(),
file_unique_id: "".to_string(),
width: 320, width: 320,
height: 320, height: 320,
file_size: Some(3452), file_size: Some(3452),

View file

@ -117,6 +117,12 @@ pub enum NonPrivateChatKind {
/// ///
/// [`Bot::get_chat`]: crate::Bot::get_chat /// [`Bot::get_chat`]: crate::Bot::get_chat
permissions: Option<ChatPermissions>, permissions: Option<ChatPermissions>,
/// The minimum allowed delay between consecutive messages sent by each
/// unpriviledged user. Returned only in [`Bot::get_chat`].
///
/// [`Bot::get_chat`]: crate::Bot::get_chat
slow_mode_delay: Option<i32>,
}, },
} }

View file

@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize};
use crate::types::User; use crate::types::User;
// TODO: ChatMemberKind?...
/// This object contains information about one member of the chat. /// This object contains information about one member of the chat.
/// ///
/// [The official docs](https://core.telegram.org/bots/api#chatmember). /// [The official docs](https://core.telegram.org/bots/api#chatmember).
@ -13,6 +14,9 @@ pub struct ChatMember {
/// The member's status in the chat. /// The member's status in the chat.
pub status: ChatMemberStatus, pub status: ChatMemberStatus,
/// Owner and administrators only. Custom title for this user
pub custom_title: Option<String>,
/// Restricted and kicked only. Date when restrictions will be lifted for /// Restricted and kicked only. Date when restrictions will be lifted for
/// this user, unix time. /// this user, unix time.
pub until_date: Option<i32>, pub until_date: Option<i32>,
@ -123,6 +127,7 @@ mod tests {
language_code: None, language_code: None,
}, },
status: ChatMemberStatus::Creator, status: ChatMemberStatus::Creator,
custom_title: None,
until_date: Some(123_456), until_date: Some(123_456),
can_be_edited: Some(true), can_be_edited: Some(true),
can_change_info: Some(true), can_change_info: Some(true),

View file

@ -10,8 +10,18 @@ pub struct ChatPhoto {
/// not changed. /// not changed.
pub small_file_id: String, pub small_file_id: String,
/// Unique file identifier of small (160x160) chat photo, which is supposed
/// to be the same over time and for different bots. Can't be used to
/// download or reuse the file.
pub small_file_unique_id: String,
/// A file identifier of big (640x640) chat photo. This file_id can be used /// A file identifier of big (640x640) chat photo. This file_id can be used
/// only for photo download and only for as long as the photo is not /// only for photo download and only for as long as the photo is not
/// changed. /// changed.
pub big_file_id: String, pub big_file_id: String,
/// Unique file identifier of big (640x640) chat photo, which is supposed
/// to be the same over time and for different bots. Can't be used to
/// download or reuse the file.
pub big_file_unique_id: String,
} }

View file

@ -16,6 +16,11 @@ pub struct Document {
/// An identifier for this file. /// An identifier for this file.
pub file_id: String, pub file_id: String,
/// Unique identifier for this file, which is supposed to be the same over
/// time and for different bots. Can't be used to download or reuse the
/// file.
pub file_unique_id: String,
/// A document thumbnail as defined by a sender. /// A document thumbnail as defined by a sender.
pub thumb: Option<PhotoSize>, pub thumb: Option<PhotoSize>,

View file

@ -22,6 +22,7 @@ pub struct EncryptedPassportElement {
#[serde_with_macros::skip_serializing_none] #[serde_with_macros::skip_serializing_none]
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] #[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
#[allow(clippy::large_enum_variant)]
pub enum EncryptedPassportElementKind { pub enum EncryptedPassportElementKind {
PersonalDetails { PersonalDetails {
/// Base64-encoded encrypted Telegram Passport element data provided /// Base64-encoded encrypted Telegram Passport element data provided

View file

@ -13,6 +13,11 @@ pub struct File {
/// Identifier for this file. /// Identifier for this file.
pub file_id: String, pub file_id: String,
/// Unique identifier for this file, which is supposed to be the same over
/// time and for different bots. Can't be used to download or reuse the
/// file.
pub file_unique_id: String,
/// File size, if known. /// File size, if known.
pub file_size: u32, pub file_size: u32,

View file

@ -91,12 +91,12 @@ mod tests {
reply_markup: Some(InlineKeyboardMarkup::new()), reply_markup: Some(InlineKeyboardMarkup::new()),
input_message_content: Some(InputMessageContent::Text { input_message_content: Some(InputMessageContent::Text {
message_text: String::from("message_text"), message_text: String::from("message_text"),
parse_mode: Some(ParseMode::Markdown), parse_mode: Some(ParseMode::MarkdownV2),
disable_web_page_preview: Some(true), disable_web_page_preview: Some(true),
}), }),
}); });
let expected_json = r#"{"type":"audio","id":"id","audio_file_id":"audio_file_id","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"Markdown","disable_web_page_preview":true}}"#; let expected_json = r#"{"type":"audio","id":"id","audio_file_id":"audio_file_id","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","disable_web_page_preview":true}}"#;
let actual_json = serde_json::to_string(&structure).unwrap(); let actual_json = serde_json::to_string(&structure).unwrap();
assert_eq!(expected_json, actual_json); assert_eq!(expected_json, actual_json);

View file

@ -827,11 +827,13 @@ mod tests {
"mime_type": "video/mp4", "mime_type": "video/mp4",
"thumb": { "thumb": {
"file_id": "AAQCAAOmBAACBf2oS53pByA-I4CWWCObDwAEAQAHbQADMWcAAhYE", "file_id": "AAQCAAOmBAACBf2oS53pByA-I4CWWCObDwAEAQAHbQADMWcAAhYE",
"file_unique_id":"",
"file_size": 10339, "file_size": 10339,
"width": 256, "width": 256,
"height": 320 "height": 320
}, },
"file_id": "BAADAgADpgQAAgX9qEud6QcgPiOAlhYE", "file_id": "BAADAgADpgQAAgX9qEud6QcgPiOAlhYE",
"file_unique_id":"",
"file_size": 1381334 "file_size": 1381334
} }
}"#; }"#;
@ -867,11 +869,13 @@ mod tests {
"mime_type": "video/mp4", "mime_type": "video/mp4",
"thumb": { "thumb": {
"file_id": "AAQCAAOmBAACBf2oS53pByA-I4CWWCObDwAEAQAHbQADMWcAAhYE", "file_id": "AAQCAAOmBAACBf2oS53pByA-I4CWWCObDwAEAQAHbQADMWcAAhYE",
"file_unique_id":"",
"file_size": 10339, "file_size": 10339,
"width": 256, "width": 256,
"height": 320 "height": 320
}, },
"file_id": "BAADAgADpgQAAgX9qEud6QcgPiOAlhYE", "file_id": "BAADAgADpgQAAgX9qEud6QcgPiOAlhYE",
"file_unique_id":"",
"file_size": 1381334 "file_size": 1381334
} }
}"#; }"#;
@ -933,11 +937,13 @@ mod tests {
"is_animated": true, "is_animated": true,
"thumb": { "thumb": {
"file_id": "AAQCAAMjAAOw0PgMaabKAcaXKCBLubkPAAQBAAdtAAPGKwACFgQ", "file_id": "AAQCAAMjAAOw0PgMaabKAcaXKCBLubkPAAQBAAdtAAPGKwACFgQ",
"file_unique_id":"",
"file_size": 4118, "file_size": 4118,
"width": 128, "width": 128,
"height": 128 "height": 128
}, },
"file_id": "CAADAgADIwADsND4DGmmygHGlyggFgQ", "file_id": "CAADAgADIwADsND4DGmmygHGlyggFgQ",
"file_unique_id":"",
"file_size": 16639 "file_size": 16639
} }
}"#; }"#;
@ -968,18 +974,21 @@ mod tests {
"photo": [ "photo": [
{ {
"file_id": "AgADAgAD36sxG-PX0UvQSXIn9rccdw-ACA4ABAEAAwIAA20AAybcBAABFgQ", "file_id": "AgADAgAD36sxG-PX0UvQSXIn9rccdw-ACA4ABAEAAwIAA20AAybcBAABFgQ",
"file_unique_id":"",
"file_size": 18188, "file_size": 18188,
"width": 320, "width": 320,
"height": 239 "height": 239
}, },
{ {
"file_id": "AgADAgAD36sxG-PX0UvQSXIn9rccdw-ACA4ABAEAAwIAA3gAAyfcBAABFgQ", "file_id": "AgADAgAD36sxG-PX0UvQSXIn9rccdw-ACA4ABAEAAwIAA3gAAyfcBAABFgQ",
"file_unique_id":"",
"file_size": 62123, "file_size": 62123,
"width": 800, "width": 800,
"height": 598 "height": 598
}, },
{ {
"file_id": "AgADAgAD36sxG-PX0UvQSXIn9rccdw-ACA4ABAEAAwIAA3kAAyTcBAABFgQ", "file_id": "AgADAgAD36sxG-PX0UvQSXIn9rccdw-ACA4ABAEAAwIAA3kAAyTcBAABFgQ",
"file_unique_id":"",
"file_size": 75245, "file_size": 75245,
"width": 962, "width": 962,
"height": 719 "height": 719

View file

@ -35,6 +35,8 @@ pub enum MessageEntityKind {
Pre, Pre,
TextLink { url: String }, TextLink { url: String },
TextMention { user: User }, TextMention { user: User },
Underline,
Strikethrough,
} }
#[test] #[test]

View file

@ -1,78 +1,132 @@
use serde::export::TryFrom; // see https://github.com/rust-lang/rust/issues/38832
// (for built ins there no warnings, but for (De)Serialize, there are)
#![allow(deprecated)]
use std::{str::FromStr, convert::TryFrom}
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::str::FromStr;
/// ## Formatting options /// ## Formatting options
/// The Bot API supports basic formatting for messages. /// The Bot API supports basic formatting for messages. You can use bold,
/// You can use **bold** and *italic* text, as well as [inline links](https://example.com) /// italic, underlined and strikethrough text, as well as inline links and
/// and `pre-formatted code` in your bots' messages. Telegram clients will /// pre-formatted code in your bots' messages. Telegram clients will render
/// render them accordingly. You can use either markdown-style or HTML-style /// them accordingly. You can use either markdown-style or HTML-style
/// formatting. /// formatting.
/// ///
/// Note that Telegram clients will display an alert to the user before opening /// Note that Telegram clients will display an **alert** to the user before
/// an inline link (Open this link? together with the full URL). /// opening an inline link (Open this link? together with the full URL).
/// ///
/// Links `tg://user?id=<user_id>` can be used to mention a user by their id /// Links `tg://user?id=<user_id>` can be used to mention a user by their ID
/// without using a username. Please note: /// without using a username. Please note:
/// ///
/// - These links will work only if they are used inside an inline link. For /// - These links will work **only** if they are used inside an inline link. For
/// example, they will not work, when used in an inline keyboard button or in /// example, they will not work, when used in an inline keyboard button or in
/// a message text. /// a message text.
/// - The mentions are only guaranteed to work if: **A**. the user is a member /// - These mentions are only guaranteed to work if the user has contacted the
/// in the group where he was mentioned or **B**. the user has contacted the /// bot in the past, has sent a callback query to the bot via inline button or
/// bot in the past or has sent a callback query to the bot via inline button /// is a member in the group where he was mentioned.
/// and has not restricted linking to their account in `Settings > Privacy &
/// Security > Forwarded Messages`.
/// ///
/// ## Markdown style /// ## MarkdownV2 style
/// To use this mode, pass [Markdown] in the `parse_mode` field when using
/// [SendMessage] (or other methods).
/// ///
/// To use this mode, pass [`MarkdownV2`] in the `parse_mode` field.
/// Use the following syntax in your message: /// Use the following syntax in your message:
/// /// ````text
/// <pre> /// *bold \*text*
/// *bold text* /// _italic \*text_
/// _italic text_ /// __underline__
/// ~strikethrough~
/// *bold _italic bold ~italic bold strikethrough~ __underline italic bold___ bold*
/// [inline URL](http://www.example.com/) /// [inline URL](http://www.example.com/)
/// [inline mention of a user](tg://user?id=123456789) /// [inline mention of a user](tg://user?id=123456789)
/// &#96;inline fixed-width code&#96; /// `inline fixed-width code`
/// &#96;&#96;&#96;block_language /// ```
/// pre-formatted fixed-width code block /// pre-formatted fixed-width code block
/// &#96;&#96;&#96; /// ```
/// </pre> /// ```rust
/// pre-formatted fixed-width code block written in the Rust programming
/// language ```
/// ````
///
/// Please note:
/// - Any character between 1 and 126 inclusively can be escaped anywhere with a
/// preceding '\' character, in which case it is treated as an ordinary
/// character and not a part of the markup.
/// - Inside `pre` and `code` entities, all '` and \ characters must be
/// escaped with a preceding \' character.
/// - Inside `(...)` part of inline link definition, all ') and \ must be
/// escaped with a preceding \' character.
/// - In all other places characters _, *, [, ], (, ), ~, `,
/// >, #, +, +, -, |, {, }, ., ! must be escaped with the
/// preceding character \'.
/// - In case of ambiguity between `italic` and `underline` entities __ is
/// always greadily treated from left to right as beginning or end of
/// `underline` entity, so instead of `___italic underline___` use `___italic
/// underline_\r__`, where `\r` is a character with code `13`, which will be
/// ignored.
/// ///
/// ## HTML style /// ## HTML style
/// To use this mode, pass [HTML] in the `parse_mode` field when using /// To use this mode, pass [`HTML`] in the `parse_mode` field.
/// [SendMessage] (or other methods).
///
/// The following tags are currently supported: /// The following tags are currently supported:
/// /// ````text
/// <pre> /// <b>bold</b>, <strong>bold</strong>
/// &lt;b&gt;bold&lt;/b&gt;, &lt;strong&gt;bold&lt;/strong&gt; /// <i>italic</i>, <em>italic</em>
/// &lt;i&gt;italic&lt;/i&gt;, &lt;em&gt;italic&lt;/em&gt; /// <u>underline</u>, <ins>underline</ins>
/// &lt;a href="http://www.example.com/"&gt;inline URL&lt;/a&gt; /// <s>strikethrough</s>, <strike>strikethrough</strike>,
/// &lt;a href="tg://user?id=123456789"&gt;inline mention of a user&lt;/a&gt; /// <del>strikethrough</del> <b>bold <i>italic bold <s>italic bold
/// &lt;code&gt;inline fixed-width code&lt;/code&gt; /// strikethrough</s> <u>underline italic bold</u></i> bold</b> <a href="http:// www.example.com/">inline URL</a>
/// &lt;pre&gt;pre-formatted fixed-width code block&lt;/pre&gt; /// <a href="tg:// user?id=123456789">inline mention of a user</a>
/// </pre> /// <code>inline fixed-width code</code>
/// <pre>pre-formatted fixed-width code block</pre>
/// <pre><code class="language-rust">pre-formatted fixed-width code block
/// written in the Rust programming language</code></pre> ````
/// ///
/// Please note: /// Please note:
/// ///
/// - Only the tags mentioned above are currently supported. /// - Only the tags mentioned above are currently supported.
/// - Tags must not be nested.
/// - All `<`, `>` and `&` symbols that are not a part of a tag or an HTML /// - All `<`, `>` and `&` symbols that are not a part of a tag or an HTML
/// entity must be replaced with the corresponding HTML entities (`<` with /// entity must be replaced with the corresponding HTML entities (`<` with
/// `&lt;`, `>` with `&gt;` and `&` with `&amp;`). /// `&lt;`, `>` with `&gt;` and `&` with `&amp;`).
/// - All numerical HTML entities are supported. /// - All numerical HTML entities are supported.
/// - The API currently supports only the following named HTML entities: `&lt;`, /// - The API currently supports only the following named HTML entities: `&lt;`,
/// `&gt;`, `&amp;` and `&quot;`. /// `&gt;`, `&amp;` and `&quot;`.
/// - Use nested `pre` and `code` tags, to define programming language for `pre`
/// entity.
/// - Programming language can't be specified for standalone `code` tags.
/// ///
/// [Markdown]: crate::types::ParseMode::Markdown /// ## Markdown style
/// [HTML]: crate::types::ParseMode::HTML /// This is a legacy mode, retained for backward compatibility. To use this
/// [SendMessage]: crate::requests::payloads::SendMessage /// mode, pass [`Markdown`] in the `parse_mode` field.
/// Use the following syntax in your message:
/// ````text
/// *bold text*
/// _italic text_
/// [inline URL](http://www.example.com/)
/// [inline mention of a user](tg://user?id=123456789)
/// `inline fixed-width code`
/// ```rust
/// pre-formatted fixed-width code block written in the Rust programming
/// language ```
/// ````
///
/// Please note:
/// - Entities must not be nested, use parse mode [`MarkdownV2`] instead.
/// - There is no way to specify underline and strikethrough entities, use parse
/// mode [`MarkdownV2`] instead.
/// - To escape characters _, *, `, [ outside of an entity, prepend the
/// characters \' before them.
/// - Escaping inside entities is not allowed, so entity must be closed first
/// and reopened again: use `_snake_\__case_` for italic `snake_case` and
/// `*2*\**2=4*` for bold `2*2=4`.
///
/// [`MarkdownV2`]: ParseMode::MarkdownV2
/// [`HTML`]: ParseMode::HTML
/// [`Markdown`]: ParseMode::Markdown
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] #[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum ParseMode { pub enum ParseMode {
MarkdownV2,
HTML, HTML,
#[deprecated = "This is a legacy mode, retained for backward \
compatibility. Use `MarkdownV2` instead."]
Markdown, Markdown,
} }
@ -117,6 +171,8 @@ impl FromStr for ParseMode {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#![allow(deprecated)]
use super::*; use super::*;
#[test] #[test]

View file

@ -10,6 +10,11 @@ pub struct PassportFile {
/// Identifier for this file. /// Identifier for this file.
pub file_id: String, pub file_id: String,
/// Unique identifier for this file, which is supposed to be the same over
/// time and for different bots. Can't be used to download or reuse the
/// file.
pub file_unique_id: String,
/// File size. /// File size.
pub file_size: u64, pub file_size: u64,

View file

@ -10,6 +10,11 @@ pub struct PhotoSize {
/// Identifier for this file. /// Identifier for this file.
pub file_id: String, pub file_id: String,
/// Unique identifier for this file, which is supposed to be the same over
/// time and for different bots. Can't be used to download or reuse the
/// file.
pub file_unique_id: String,
/// Photo width. /// Photo width.
pub width: i32, pub width: i32,
@ -26,10 +31,11 @@ mod tests {
#[test] #[test]
fn deserialize() { fn deserialize() {
let json = r#"{"file_id":"id","width":320,"height":320, let json = r#"{"file_id":"id","file_unique_id":"","width":320,"height":320,
"file_size":3452}"#; "file_size":3452}"#;
let expected = PhotoSize { let expected = PhotoSize {
file_id: "id".to_string(), file_id: "id".to_string(),
file_unique_id: "".to_string(),
width: 320, width: 320,
height: 320, height: 320,
file_size: Some(3452), file_size: Some(3452),

View file

@ -11,6 +11,11 @@ pub struct Sticker {
/// Identifier for this file. /// Identifier for this file.
pub file_id: String, pub file_id: String,
/// Unique identifier for this file, which is supposed to be the same over
/// time and for different bots. Can't be used to download or reuse the
/// file.
pub file_unique_id: String,
/// Sticker width. /// Sticker width.
pub width: u16, pub width: u16,

View file

@ -11,6 +11,11 @@ pub struct Video {
/// Identifier for this file. /// Identifier for this file.
pub file_id: String, pub file_id: String,
/// Unique identifier for this file, which is supposed to be the same over
/// time and for different bots. Can't be used to download or reuse the
/// file.
pub file_unique_id: String,
/// Video width as defined by sender. /// Video width as defined by sender.
pub width: u32, pub width: u32,

View file

@ -15,6 +15,11 @@ pub struct VideoNote {
/// Identifier for this file. /// Identifier for this file.
pub file_id: String, pub file_id: String,
/// Unique identifier for this file, which is supposed to be the same over
/// time and for different bots. Can't be used to download or reuse the
/// file.
pub file_unique_id: String,
/// Video width and height (diameter of the video message) as defined by /// Video width and height (diameter of the video message) as defined by
/// sender. /// sender.
pub length: u32, pub length: u32,

View file

@ -9,6 +9,11 @@ pub struct Voice {
/// Identifier for this file. /// Identifier for this file.
pub file_id: String, pub file_id: String,
/// Unique identifier for this file, which is supposed to be the same over
/// time and for different bots. Can't be used to download or reuse the
/// file.
pub file_unique_id: String,
/// Duration of the audio in seconds as defined by sender. /// Duration of the audio in seconds as defined by sender.
pub duration: u32, pub duration: u32,