mirror of
https://github.com/teloxide/teloxide.git
synced 2024-12-22 14:35:36 +01:00
Fix ParseMode
, InputFile
and InputMedia
(add to module tree, add docs, etc)
This commit is contained in:
parent
d8c70b9fc6
commit
38b5945ec8
5 changed files with 323 additions and 65 deletions
|
@ -1,4 +0,0 @@
|
|||
pub enum ParseMode {
|
||||
HTML,
|
||||
Markdown,
|
||||
}
|
|
@ -1,8 +1,25 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Deserialize, Hash, PartialEq, Eq)]
|
||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||
pub enum InputFile {
|
||||
File(std::fs::File),
|
||||
File(std::path::PathBuf),
|
||||
Url(String),
|
||||
FileId(String),
|
||||
}
|
||||
|
||||
impl serde::Serialize for InputFile {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
|
||||
match self {
|
||||
InputFile::File(path) => {
|
||||
// NOTE: file should be actually attached with multipart/form-data
|
||||
serializer.serialize_str(
|
||||
// TODO: remove unwrap (?)
|
||||
&format!("attach://{}", path.file_name().unwrap().to_string_lossy())
|
||||
)
|
||||
},
|
||||
InputFile::Url(url) => serializer.serialize_str(url),
|
||||
InputFile::FileId(id) => serializer.serialize_str(id),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,69 +1,245 @@
|
|||
use serde::Deserialize;
|
||||
use crate::core::types::InputFile;
|
||||
use crate::core::types::{InputFile, ParseMode};
|
||||
|
||||
// TODO: should variants use new-type?
|
||||
#[derive(Debug, Serialize, PartialEq, Eq)]
|
||||
#[serde(tag = "type")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
/// This object represents the content of a media message to be sent.
|
||||
/// [More](https://core.telegram.org/bots/api#inputmedia)
|
||||
pub enum InputMedia {
|
||||
InputMediaPhoto(InputMediaPhoto),
|
||||
InputMediaVideo(InputMediaVideo),
|
||||
InputMediaAnimation(InputMediaAnimation),
|
||||
InputMediaAudio(InputMediaAudiotype),
|
||||
InputMediaDocument(InputMediaDocument),
|
||||
/// Represents a photo to be sent.
|
||||
Photo {
|
||||
/// File to send.
|
||||
media: InputFile,
|
||||
/// Caption of the photo to be sent, 0-1024 characters
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
caption: Option<String>,
|
||||
/// Send [Markdown] or [HTML],
|
||||
/// if you want Telegram apps to show [bold, italic, fixed-width text or inline URLs]
|
||||
/// in the media caption.
|
||||
///
|
||||
/// [Markdown]: crate::core::types::ParseMode::Markdown
|
||||
/// [Html]: crate::core::types::ParseMode::Html
|
||||
/// [bold, italic, fixed-width text or inline URLs]: crate::core::types::ParseMode
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
parse_mode: Option<ParseMode>,
|
||||
},
|
||||
Video {
|
||||
/// File to send.File to send.
|
||||
media: InputFile,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
/// 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 [InputFile::File].
|
||||
///
|
||||
/// [InputFile::File]: crate::core::types::InputFile::File
|
||||
thumb: Option<InputFile>,
|
||||
/// Caption of the video to be sent, 0-1024 characters.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
caption: Option<String>,
|
||||
/// Send [Markdown] or [HTML],
|
||||
/// if you want Telegram apps to show [bold, italic, fixed-width text or inline URLs]
|
||||
/// in the media caption.
|
||||
///
|
||||
/// [Markdown]: crate::core::types::ParseMode::Markdown
|
||||
/// [Html]: crate::core::types::ParseMode::Html
|
||||
/// [bold, italic, fixed-width text or inline URLs]: crate::core::types::ParseMode
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
parse_mode: Option<ParseMode>,
|
||||
/// Video width
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
width: Option<u16>,
|
||||
/// Video height
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
height: Option<u16>,
|
||||
/// Video duration
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
duration: Option<u16>,
|
||||
/// Pass `true`, if the uploaded video is suitable for streaming
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
supports_streaming: Option<bool>,
|
||||
},
|
||||
/// Represents an animation file (GIF or H.264/MPEG-4 AVC video without sound) to be sent.
|
||||
Animation {
|
||||
/// File to send.
|
||||
media: InputFile,
|
||||
/// 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 [InputFile::File].
|
||||
///
|
||||
/// [InputFile::File]: crate::core::types::InputFile::File
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
thumb: Option<InputFile>,
|
||||
/// Caption of the animation to be sent, 0-1024 characters
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
caption: Option<String>,
|
||||
/// Send [Markdown] or [HTML],
|
||||
/// if you want Telegram apps to show [bold, italic, fixed-width text or inline URLs]
|
||||
/// in the media caption.
|
||||
///
|
||||
/// [Markdown]: crate::core::types::ParseMode::Markdown
|
||||
/// [Html]: crate::core::types::ParseMode::Html
|
||||
/// [bold, italic, fixed-width text or inline URLs]: crate::core::types::ParseMode
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
parse_mode: Option<ParseMode>,
|
||||
/// Animation width
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
width: Option<u16>,
|
||||
/// Animation height
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
height: Option<u16>,
|
||||
/// Animation duration
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
duration: Option<u16>,
|
||||
},
|
||||
/// Represents an audio file to be treated as music to be sent.
|
||||
Audio {
|
||||
/// File to send,
|
||||
media: InputFile,
|
||||
/// 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 [InputFile::File].
|
||||
///
|
||||
/// [InputFile::File]: crate::core::types::InputFile::File
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
thumb: Option<InputFile>,
|
||||
/// Caption of the audio to be sent, 0-1024 characters
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
caption: Option<String>,
|
||||
/// Send [Markdown] or [HTML],
|
||||
/// if you want Telegram apps to show [bold, italic, fixed-width text or inline URLs]
|
||||
/// in the media caption.
|
||||
///
|
||||
/// [Markdown]: crate::core::types::ParseMode::Markdown
|
||||
/// [Html]: crate::core::types::ParseMode::Html
|
||||
/// [bold, italic, fixed-width text or inline URLs]: crate::core::types::ParseMode
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
parse_mode: Option<String>,
|
||||
/// Duration of the audio in seconds
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
duration: Option<u16>,
|
||||
/// Performer of the audio
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
performer: Option<String>,
|
||||
/// Title of the audio
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
title: Option<String>
|
||||
},
|
||||
/// Represents a general file to be sent.
|
||||
Document {
|
||||
/// File to send.
|
||||
media: InputFile,
|
||||
/// 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 [InputFile::File].
|
||||
///
|
||||
/// [InputFile::File]: crate::core::types::InputFile::File
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
thumb: Option<InputFile>,
|
||||
/// Caption of the document to be sent, 0-1024 characters
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
caption: Option<String>,
|
||||
/// Send [Markdown] or [HTML],
|
||||
/// if you want Telegram apps to show [bold, italic, fixed-width text or inline URLs]
|
||||
/// in the media caption.
|
||||
///
|
||||
/// [Markdown]: crate::core::types::ParseMode::Markdown
|
||||
/// [Html]: crate::core::types::ParseMode::Html
|
||||
/// [bold, italic, fixed-width text or inline URLs]: crate::core::types::ParseMode
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
parse_mode: Option<ParseMode>,
|
||||
},
|
||||
}
|
||||
|
||||
pub enum ThumbKind {
|
||||
InputFile,
|
||||
String,
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct InputMediaPhoto {
|
||||
type_: String,
|
||||
media: String,
|
||||
caption: Option<String>,
|
||||
parse_mode: Option<String>,
|
||||
}
|
||||
#[test]
|
||||
fn photo_serialize() {
|
||||
let expected_json = r#"{"type":"photo","media":"123456"}"#;
|
||||
let photo = InputMedia::Photo {
|
||||
media: InputFile::FileId(String::from("123456")),
|
||||
caption: None,
|
||||
parse_mode: None,
|
||||
};
|
||||
|
||||
#[derive(Debug, Serialize), Deserialize]
|
||||
pub struct InputMediaVideo {
|
||||
type_: String,
|
||||
media: String,
|
||||
thumb: ThumbKind,
|
||||
caption: Option<String>,
|
||||
parse_mode: Option<String>,
|
||||
width: Option<i64>,
|
||||
height: Option<i64>,
|
||||
duration: Option<i64>,
|
||||
supports_streaming: Option<bool>,
|
||||
}
|
||||
let actual_json = serde_json::to_string(&photo).unwrap();
|
||||
assert_eq!(expected_json, actual_json);
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct InputMediaAnimation {
|
||||
type_: String,
|
||||
media: String,
|
||||
thumb: Option<ThumbKind>,
|
||||
caption: Option<String>,
|
||||
parse_mode: Option<String>,
|
||||
width: Option<i64>,
|
||||
height: Option<i64>,
|
||||
duration: Option<i64>,
|
||||
}
|
||||
#[test]
|
||||
fn video_serialize() {
|
||||
let expected_json = r#"{"type":"video","media":"123456"}"#;
|
||||
let video = InputMedia::Video {
|
||||
media: InputFile::FileId(String::from("123456")),
|
||||
thumb: None,
|
||||
caption: None,
|
||||
parse_mode: None,
|
||||
width: None,
|
||||
height: None,
|
||||
duration: None,
|
||||
supports_streaming: None,
|
||||
};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct InputMediaAudio {
|
||||
type_: String,
|
||||
media: String,
|
||||
thumb: Option<ThumbKind>,
|
||||
caption: Option<String>,
|
||||
parse_mode: Option<String>,
|
||||
duration: Option<i64>,
|
||||
performer: Option<i64>,
|
||||
title: Option<String>
|
||||
}
|
||||
let actual_json = serde_json::to_string(&video).unwrap();
|
||||
assert_eq!(expected_json, actual_json);
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct InputMediaDocument {
|
||||
type_: String,
|
||||
media: String,
|
||||
thumb: Option<ThumbKind>,
|
||||
caption: Option<String>,
|
||||
parse_mode: parse_mode,
|
||||
}
|
||||
#[test]
|
||||
fn animation_serialize() {
|
||||
let expected_json = r#"{"type":"animation","media":"123456"}"#;
|
||||
let video = InputMedia::Animation {
|
||||
media: InputFile::FileId(String::from("123456")),
|
||||
thumb: None,
|
||||
caption: None,
|
||||
parse_mode: None,
|
||||
width: None,
|
||||
height: None,
|
||||
duration: None,
|
||||
};
|
||||
|
||||
let actual_json = serde_json::to_string(&video).unwrap();
|
||||
assert_eq!(expected_json, actual_json);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn audio_serialize() {
|
||||
let expected_json = r#"{"type":"audio","media":"123456"}"#;
|
||||
let video = InputMedia::Audio {
|
||||
media: InputFile::FileId(String::from("123456")),
|
||||
thumb: None,
|
||||
caption: None,
|
||||
parse_mode: None,
|
||||
duration: None,
|
||||
performer: None,
|
||||
title: None
|
||||
};
|
||||
|
||||
let actual_json = serde_json::to_string(&video).unwrap();
|
||||
assert_eq!(expected_json, actual_json);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn document_serialize() {
|
||||
let expected_json = r#"{"type":"document","media":"123456"}"#;
|
||||
let video = InputMedia::Document {
|
||||
media: InputFile::FileId(String::from("123456")),
|
||||
thumb: None,
|
||||
caption: None,
|
||||
parse_mode: None,
|
||||
};
|
||||
|
||||
let actual_json = serde_json::to_string(&video).unwrap();
|
||||
assert_eq!(expected_json, actual_json);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,9 @@ pub use self::{
|
|||
sticker::Sticker,
|
||||
successful_payment::SuccessfulPayment,
|
||||
user::User,
|
||||
input_file::InputFile,
|
||||
input_media::InputMedia,
|
||||
parse_mode::ParseMode,
|
||||
};
|
||||
|
||||
mod answer_pre_checkout_query;
|
||||
|
@ -43,3 +46,6 @@ mod shipping_query;
|
|||
mod sticker;
|
||||
mod successful_payment;
|
||||
mod user;
|
||||
mod input_file;
|
||||
mod input_media;
|
||||
mod parse_mode;
|
||||
|
|
63
src/core/types/parse_mode.rs
Normal file
63
src/core/types/parse_mode.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
/// ## Formatting options
|
||||
/// The Bot API supports basic formatting for messages.
|
||||
/// You can use **bold** and *italic* text, as well as [inline links](https://example.com) and `pre-formatted code` in
|
||||
/// your bots' messages. Telegram clients will render them accordingly. You can use either
|
||||
/// markdown-style or HTML-style formatting.
|
||||
///
|
||||
/// Note that Telegram clients will display an alert to the user before 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 without using a username.
|
||||
/// Please note:
|
||||
///
|
||||
/// - 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 a message text.
|
||||
/// - The mentions are only guaranteed to work if: **A**. the user is a member in the group where he
|
||||
/// was mentioned or **B**. the user has contacted the bot in the past or has sent a callback
|
||||
/// query to the bot via inline button and has not restricted linking to their account in
|
||||
/// `Settings > Privacy & Security > Forwarded Messages`.
|
||||
///
|
||||
/// ## Markdown style
|
||||
/// To use this mode, pass [Markdown] in the `parse_mode` field when using [SendMessage] (or other methods).
|
||||
///
|
||||
/// Use the following syntax in your message:
|
||||
///
|
||||
/// ```ignore
|
||||
/// *bold text*
|
||||
/// _italic text_
|
||||
/// [inline URL](http://www.example.com/)
|
||||
/// [inline mention of a user](tg://user?id=123456789)
|
||||
/// `inline fixed-width code`
|
||||
/// ```block_language
|
||||
/// pre-formatted fixed-width code block
|
||||
/// ```
|
||||
/// ```
|
||||
///
|
||||
/// ## HTML style
|
||||
/// To use this mode, pass [HTML] in the `parse_mode` field when using [SendMessage] (or other methods).
|
||||
///
|
||||
/// The following tags are currently supported:
|
||||
///
|
||||
/// ```ignore
|
||||
/// <b>bold</b>, <strong>bold</strong>
|
||||
/// <i>italic</i>, <em>italic</em>
|
||||
/// <a href="http://www.example.com/">inline URL</a>
|
||||
/// <a href="tg://user?id=123456789">inline mention of a user</a>
|
||||
/// <code>inline fixed-width code</code>
|
||||
/// <pre>pre-formatted fixed-width code block</pre>
|
||||
/// ```
|
||||
///
|
||||
/// Please note:
|
||||
///
|
||||
/// - 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 entity must be replaced with the corresponding HTML entities (`<` with `<`, `>` with `>` and `&` with `&`).
|
||||
/// - All numerical HTML entities are supported.
|
||||
/// - The API currently supports only the following named HTML entities: `<`, `>`, `&` and `"`.
|
||||
pub enum ParseMode {
|
||||
HTML,
|
||||
Markdown,
|
||||
}
|
Loading…
Reference in a new issue