mirror of
https://github.com/teloxide/teloxide.git
synced 2024-12-23 15:01:45 +01:00
Merge pull request #115 from teloxide/make_urls_urlier
Use `url::Url` for urls, use `chrono::DateTime<Utc>` for dates in types
This commit is contained in:
commit
3d7ca29681
34 changed files with 246 additions and 215 deletions
|
@ -8,8 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
## [unreleased]
|
## [unreleased]
|
||||||
|
|
||||||
- Add `EditedMessageIsTooLong` error [#109][pr109]
|
- Add `EditedMessageIsTooLong` error [#109][pr109]
|
||||||
|
- Use `url::Url` for urls, use `chrono::DateTime<Utc>` for dates in types ([#115][pr115])
|
||||||
|
|
||||||
[pr109]: https://github.com/teloxide/teloxide-core/pull/109
|
[pr109]: https://github.com/teloxide/teloxide-core/pull/109
|
||||||
|
[pr115]: https://github.com/teloxide/teloxide-core/pull/115
|
||||||
|
|
||||||
## 0.3.3
|
## 0.3.3
|
||||||
|
|
||||||
|
|
|
@ -485,7 +485,8 @@ impl Serializer for PartSerializer {
|
||||||
let part = Part::text(format!("attach://{}", uuid));
|
let part = Part::text(format!("attach://{}", uuid));
|
||||||
Ok((part, vec![(uuid, f)]))
|
Ok((part, vec![(uuid, f)]))
|
||||||
}
|
}
|
||||||
InputFile::FileId(s) | InputFile::Url(s) => Ok((Part::text(s), Vec::new())),
|
InputFile::FileId(s) => Ok((Part::text(s), Vec::new())),
|
||||||
|
InputFile::Url(s) => Ok((Part::text(String::from(s)), Vec::new())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,7 +587,8 @@ impl SerializeStructVariant for PartFromFile {
|
||||||
|
|
||||||
Ok((part, vec![(uuid, f)]))
|
Ok((part, vec![(uuid, f)]))
|
||||||
}
|
}
|
||||||
InputFile::FileId(s) | InputFile::Url(s) => Ok((Part::text(s), vec![])),
|
InputFile::FileId(s) => Ok((Part::text(s), vec![])),
|
||||||
|
InputFile::Url(s) => Ok((Part::text(String::from(s)), vec![])),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -615,9 +617,12 @@ impl SerializeSeq for InnerPartSerializer {
|
||||||
value["media"] = serde_json::Value::String(format!("attach://{}", uuid));
|
value["media"] = serde_json::Value::String(format!("attach://{}", uuid));
|
||||||
self.files.push((uuid, f));
|
self.files.push((uuid, f));
|
||||||
}
|
}
|
||||||
InputFile::FileId(s) | InputFile::Url(s) => {
|
InputFile::FileId(s) => {
|
||||||
value["media"] = serde_json::Value::String(s);
|
value["media"] = serde_json::Value::String(s);
|
||||||
}
|
}
|
||||||
|
InputFile::Url(s) => {
|
||||||
|
value["media"] = serde_json::Value::String(String::from(s));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.array_json_parts.push(value);
|
self.array_json_parts.push(value);
|
||||||
|
@ -673,10 +678,14 @@ impl SerializeStruct for PartSerializerStruct {
|
||||||
|
|
||||||
self.2.push((uuid, f));
|
self.2.push((uuid, f));
|
||||||
}
|
}
|
||||||
InputFile::FileId(s) | InputFile::Url(s) => {
|
InputFile::FileId(s) => {
|
||||||
SerializeStruct::serialize_field(&mut ser, key, &s)?;
|
SerializeStruct::serialize_field(&mut ser, key, &s)?;
|
||||||
self.1 = get_state(ser)
|
self.1 = get_state(ser)
|
||||||
}
|
}
|
||||||
|
InputFile::Url(s) => {
|
||||||
|
SerializeStruct::serialize_field(&mut ser, key, s.as_str())?;
|
||||||
|
self.1 = get_state(ser)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SerializeStruct::serialize_field(&mut ser, key, value)?;
|
SerializeStruct::serialize_field(&mut ser, key, value)?;
|
||||||
|
|
|
@ -84,7 +84,7 @@ fn test() {
|
||||||
let value = String::from("test");
|
let value = String::from("test");
|
||||||
assert_eq!(value.serialize(StringUnserializer), Ok(value));
|
assert_eq!(value.serialize(StringUnserializer), Ok(value));
|
||||||
|
|
||||||
let value = InputFile::Url(String::from("url"));
|
let value = InputFile::Url(reqwest::Url::parse("http://example.com").unwrap());
|
||||||
assert_eq!(value.serialize(InputFileUnserializer::NotMem), Ok(value));
|
assert_eq!(value.serialize(InputFileUnserializer::NotMem), Ok(value));
|
||||||
|
|
||||||
let value = InputFile::FileId(String::from("file_id"));
|
let value = InputFile::FileId(String::from("file_id"));
|
||||||
|
|
|
@ -62,7 +62,9 @@ impl Serializer for InputFileUnserializer {
|
||||||
// TODO
|
// TODO
|
||||||
match variant {
|
match variant {
|
||||||
"File" => Ok(InputFile::File(value.serialize(StringUnserializer)?.into())),
|
"File" => Ok(InputFile::File(value.serialize(StringUnserializer)?.into())),
|
||||||
"Url" => Ok(InputFile::Url(value.serialize(StringUnserializer)?)),
|
"Url" => Ok(InputFile::Url(
|
||||||
|
reqwest::Url::parse(&value.serialize(StringUnserializer)?).unwrap(),
|
||||||
|
)),
|
||||||
"FileId" => Ok(InputFile::FileId(value.serialize(StringUnserializer)?)),
|
"FileId" => Ok(InputFile::FileId(value.serialize(StringUnserializer)?)),
|
||||||
name => Err(UnserializerError::UnexpectedVariant {
|
name => Err(UnserializerError::UnexpectedVariant {
|
||||||
name,
|
name,
|
||||||
|
|
48
src/types.rs
48
src/types.rs
|
@ -221,8 +221,8 @@ mod non_telegram_types {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) mod serde_opt_date_from_unix_timestamp {
|
pub(crate) mod serde_opt_date_from_unix_timestamp {
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||||
use serde::{Serialize, Serializer};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
pub(crate) fn serialize<S>(
|
pub(crate) fn serialize<S>(
|
||||||
this: &Option<DateTime<Utc>>,
|
this: &Option<DateTime<Utc>>,
|
||||||
|
@ -234,14 +234,42 @@ pub(crate) mod serde_opt_date_from_unix_timestamp {
|
||||||
this.map(|dt| dt.timestamp()).serialize(serializer)
|
this.map(|dt| dt.timestamp()).serialize(serializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub(crate) fn deserialize<'de, D>(deserializer: D) ->
|
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Option<DateTime<Utc>>, D::Error>
|
||||||
// Result<Option<DateTime<Utc>>, D::Error> where
|
where
|
||||||
// D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
// {
|
{
|
||||||
// Ok(Option::<i64>::deserialize(deserializer)?
|
Ok(Option::<i64>::deserialize(deserializer)?
|
||||||
// .map(|timestamp|
|
.map(|timestamp| DateTime::from_utc(NaiveDateTime::from_timestamp(timestamp, 0), Utc)))
|
||||||
// DateTime::from_utc(NaiveDateTime::from_timestamp(timestamp, 0), Utc)))
|
}
|
||||||
// }
|
|
||||||
|
pub(crate) fn none<T>() -> Option<T> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test() {
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct Struct {
|
||||||
|
#[serde(with = "crate::types::serde_opt_date_from_unix_timestamp")]
|
||||||
|
#[serde(default = "crate::types::serde_opt_date_from_unix_timestamp::none")]
|
||||||
|
date: Option<DateTime<Utc>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let json = r#"{"date":1}"#;
|
||||||
|
let expected = DateTime::from_utc(NaiveDateTime::from_timestamp(1, 0), Utc);
|
||||||
|
|
||||||
|
let Struct { date } = serde_json::from_str(json).unwrap();
|
||||||
|
assert_eq!(date, Some(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let json = r#"{}"#;
|
||||||
|
|
||||||
|
let Struct { date } = serde_json::from_str(json).unwrap();
|
||||||
|
assert_eq!(date, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) mod serde_date_from_unix_timestamp {
|
pub(crate) mod serde_date_from_unix_timestamp {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::types::User;
|
use crate::types::User;
|
||||||
|
@ -13,9 +14,11 @@ pub struct ChatInviteLink {
|
||||||
pub is_primary: bool,
|
pub is_primary: bool,
|
||||||
/// `true`, if the link is revoked
|
/// `true`, if the link is revoked
|
||||||
pub is_revoked: bool,
|
pub is_revoked: bool,
|
||||||
/// Point in time (Unix timestamp) when the link will expire or has been
|
/// Point in time when the link will expire or has been
|
||||||
/// expired
|
/// expired
|
||||||
pub expire_date: Option<i64>,
|
#[serde(with = "crate::types::serde_opt_date_from_unix_timestamp")]
|
||||||
|
#[serde(default = "crate::types::serde_opt_date_from_unix_timestamp::none")]
|
||||||
|
pub expire_date: Option<DateTime<Utc>>,
|
||||||
/// Maximum number of users that can be members of the chat simultaneously
|
/// Maximum number of users that can be members of the chat simultaneously
|
||||||
/// after joining the chat via this invite link; 1-99999
|
/// after joining the chat via this invite link; 1-99999
|
||||||
pub member_limit: Option<u32>,
|
pub member_limit: Option<u32>,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::types::{Chat, ChatInviteLink, ChatMember, User};
|
use crate::types::{Chat, ChatInviteLink, ChatMember, User};
|
||||||
|
@ -8,8 +9,9 @@ pub struct ChatMemberUpdated {
|
||||||
pub chat: Chat,
|
pub chat: Chat,
|
||||||
/// Performer of the action, which resulted in the change
|
/// Performer of the action, which resulted in the change
|
||||||
pub from: User,
|
pub from: User,
|
||||||
/// Date the change was done in Unix time
|
/// Date the change was done
|
||||||
pub date: i64,
|
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
|
||||||
|
pub date: DateTime<Utc>,
|
||||||
/// Previous information about the chat member
|
/// Previous information about the chat member
|
||||||
pub old_chat_member: ChatMember,
|
pub old_chat_member: ChatMember,
|
||||||
/// New information about the chat member
|
/// New information about the chat member
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl InlineKeyboardButton {
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum InlineKeyboardButtonKind {
|
pub enum InlineKeyboardButtonKind {
|
||||||
/// HTTP or tg:// url to be opened when button is pressed.
|
/// HTTP or tg:// url to be opened when button is pressed.
|
||||||
Url(String),
|
Url(reqwest::Url),
|
||||||
|
|
||||||
/// An HTTP URL used to automatically authorize the user. Can be used as a
|
/// An HTTP URL used to automatically authorize the user. Can be used as a
|
||||||
/// replacement for the [Telegram Login Widget]().
|
/// replacement for the [Telegram Login Widget]().
|
||||||
|
@ -104,10 +104,11 @@ pub enum InlineKeyboardButtonKind {
|
||||||
/// ```
|
/// ```
|
||||||
/// use teloxide_core::types::InlineKeyboardButton;
|
/// use teloxide_core::types::InlineKeyboardButton;
|
||||||
///
|
///
|
||||||
/// let url_button = InlineKeyboardButton::url("Text".to_string(), "http://url.com".to_string());
|
/// let url = url::Url::parse("https://example.com").unwrap();
|
||||||
|
/// let url_button = InlineKeyboardButton::url("Text".to_string(), url);
|
||||||
/// ```
|
/// ```
|
||||||
impl InlineKeyboardButton {
|
impl InlineKeyboardButton {
|
||||||
pub fn url(text: String, url: String) -> InlineKeyboardButton {
|
pub fn url(text: String, url: reqwest::Url) -> InlineKeyboardButton {
|
||||||
InlineKeyboardButton {
|
InlineKeyboardButton {
|
||||||
text,
|
text,
|
||||||
kind: InlineKeyboardButtonKind::Url(url),
|
kind: InlineKeyboardButtonKind::Url(url),
|
||||||
|
|
|
@ -26,7 +26,8 @@ pub struct InlineKeyboardMarkup {
|
||||||
/// ```
|
/// ```
|
||||||
/// use teloxide_core::types::{InlineKeyboardButton, InlineKeyboardMarkup};
|
/// use teloxide_core::types::{InlineKeyboardButton, InlineKeyboardMarkup};
|
||||||
///
|
///
|
||||||
/// let url_button = InlineKeyboardButton::url("text".to_string(), "http://url.com".to_string());
|
/// let url = url::Url::parse("https://example.com").unwrap();
|
||||||
|
/// let url_button = InlineKeyboardButton::url("text".to_string(), url);
|
||||||
/// let keyboard = InlineKeyboardMarkup::default().append_row(vec![url_button]);
|
/// let keyboard = InlineKeyboardMarkup::default().append_row(vec![url_button]);
|
||||||
/// ```
|
/// ```
|
||||||
impl InlineKeyboardMarkup {
|
impl InlineKeyboardMarkup {
|
||||||
|
@ -78,10 +79,14 @@ impl InlineKeyboardMarkup {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
fn url(n: u32) -> reqwest::Url {
|
||||||
|
reqwest::Url::parse(&format!("https://example.com/{n}", n = n)).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn append_row() {
|
fn append_row() {
|
||||||
let button1 = InlineKeyboardButton::url("text 1".to_string(), "url 1".to_string());
|
let button1 = InlineKeyboardButton::url("text 1".to_string(), url(1));
|
||||||
let button2 = InlineKeyboardButton::url("text 2".to_string(), "url 2".to_string());
|
let button2 = InlineKeyboardButton::url("text 2".to_string(), url(2));
|
||||||
|
|
||||||
let markup =
|
let markup =
|
||||||
InlineKeyboardMarkup::default().append_row(vec![button1.clone(), button2.clone()]);
|
InlineKeyboardMarkup::default().append_row(vec![button1.clone(), button2.clone()]);
|
||||||
|
@ -95,8 +100,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn append_to_row_existent_row() {
|
fn append_to_row_existent_row() {
|
||||||
let button1 = InlineKeyboardButton::url("text 1".to_string(), "url 1".to_string());
|
let button1 = InlineKeyboardButton::url("text 1".to_string(), url(1));
|
||||||
let button2 = InlineKeyboardButton::url("text 2".to_string(), "url 2".to_string());
|
let button2 = InlineKeyboardButton::url("text 2".to_string(), url(2));
|
||||||
|
|
||||||
let markup = InlineKeyboardMarkup::default()
|
let markup = InlineKeyboardMarkup::default()
|
||||||
.append_row(vec![button1.clone()])
|
.append_row(vec![button1.clone()])
|
||||||
|
@ -111,8 +116,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn append_to_row_nonexistent_row() {
|
fn append_to_row_nonexistent_row() {
|
||||||
let button1 = InlineKeyboardButton::url("text 1".to_string(), "url 1".to_string());
|
let button1 = InlineKeyboardButton::url("text 1".to_string(), url(1));
|
||||||
let button2 = InlineKeyboardButton::url("text 2".to_string(), "url 2".to_string());
|
let button2 = InlineKeyboardButton::url("text 2".to_string(), url(2));
|
||||||
|
|
||||||
let markup = InlineKeyboardMarkup::default()
|
let markup = InlineKeyboardMarkup::default()
|
||||||
.append_row(vec![button1.clone()])
|
.append_row(vec![button1.clone()])
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub struct InlineQueryResultArticle {
|
||||||
pub reply_markup: Option<InlineKeyboardMarkup>,
|
pub reply_markup: Option<InlineKeyboardMarkup>,
|
||||||
|
|
||||||
/// URL of the result.
|
/// URL of the result.
|
||||||
pub url: Option<String>,
|
pub url: Option<reqwest::Url>,
|
||||||
|
|
||||||
/// Pass `true`, if you don't want the URL to be shown in the
|
/// Pass `true`, if you don't want the URL to be shown in the
|
||||||
/// message.
|
/// message.
|
||||||
|
@ -31,7 +31,7 @@ pub struct InlineQueryResultArticle {
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
|
|
||||||
/// Url of the thumbnail for the result.
|
/// Url of the thumbnail for the result.
|
||||||
pub thumb_url: Option<String>,
|
pub thumb_url: Option<reqwest::Url>,
|
||||||
|
|
||||||
/// Thumbnail width.
|
/// Thumbnail width.
|
||||||
pub thumb_width: Option<i32>,
|
pub thumb_width: Option<i32>,
|
||||||
|
@ -86,11 +86,8 @@ impl InlineQueryResultArticle {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn url<S>(mut self, val: S) -> Self
|
pub fn url(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.url = Some(val);
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.url = Some(val.into());
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,11 +104,8 @@ impl InlineQueryResultArticle {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thumb_url<S>(mut self, val: S) -> Self
|
pub fn thumb_url<S>(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.thumb_url = Some(val);
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.thumb_url = Some(val.into());
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub struct InlineQueryResultAudio {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
|
|
||||||
/// A valid URL for the audio file.
|
/// A valid URL for the audio file.
|
||||||
pub audio_url: String,
|
pub audio_url: reqwest::Url,
|
||||||
|
|
||||||
/// Title.
|
/// Title.
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
@ -52,15 +52,14 @@ pub struct InlineQueryResultAudio {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineQueryResultAudio {
|
impl InlineQueryResultAudio {
|
||||||
pub fn new<S1, S2, S3>(id: S1, audio_url: S2, title: S3) -> Self
|
pub fn new<S1, S2>(id: S1, audio_url: reqwest::Url, title: S2) -> Self
|
||||||
where
|
where
|
||||||
S1: Into<String>,
|
S1: Into<String>,
|
||||||
S2: Into<String>,
|
S2: Into<String>,
|
||||||
S3: Into<String>,
|
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
audio_url: audio_url.into(),
|
audio_url,
|
||||||
title: title.into(),
|
title: title.into(),
|
||||||
caption: None,
|
caption: None,
|
||||||
parse_mode: None,
|
parse_mode: None,
|
||||||
|
@ -80,11 +79,8 @@ impl InlineQueryResultAudio {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn audio_url<S>(mut self, val: S) -> Self
|
pub fn audio_url(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.audio_url = val;
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.audio_url = val.into();
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ impl InlineQueryResultCachedDocument {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_mode<S>(mut self, val: ParseMode) -> Self {
|
pub fn parse_mode(mut self, val: ParseMode) -> Self {
|
||||||
self.parse_mode = Some(val);
|
self.parse_mode = Some(val);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ impl InlineQueryResultCachedMpeg4Gif {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_mode<S>(mut self, val: ParseMode) -> Self {
|
pub fn parse_mode(mut self, val: ParseMode) -> Self {
|
||||||
self.parse_mode = Some(val);
|
self.parse_mode = Some(val);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ impl InlineQueryResultCachedPhoto {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_mode<S>(mut self, val: ParseMode) -> Self {
|
pub fn parse_mode(mut self, val: ParseMode) -> Self {
|
||||||
self.parse_mode = Some(val);
|
self.parse_mode = Some(val);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ impl InlineQueryResultCachedVideo {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_mode<S>(mut self, val: ParseMode) -> Self {
|
pub fn parse_mode(mut self, val: ParseMode) -> Self {
|
||||||
self.parse_mode = Some(val);
|
self.parse_mode = Some(val);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ impl InlineQueryResultCachedVoice {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_mode<S>(mut self, val: ParseMode) -> Self {
|
pub fn parse_mode(mut self, val: ParseMode) -> Self {
|
||||||
self.parse_mode = Some(val);
|
self.parse_mode = Some(val);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ pub struct InlineQueryResultContact {
|
||||||
pub input_message_content: Option<InputMessageContent>,
|
pub input_message_content: Option<InputMessageContent>,
|
||||||
|
|
||||||
/// Url of the thumbnail for the result.
|
/// Url of the thumbnail for the result.
|
||||||
pub thumb_url: Option<String>,
|
pub thumb_url: Option<reqwest::Url>,
|
||||||
|
|
||||||
/// Thumbnail width.
|
/// Thumbnail width.
|
||||||
pub thumb_width: Option<i32>,
|
pub thumb_width: Option<i32>,
|
||||||
|
@ -119,11 +119,8 @@ impl InlineQueryResultContact {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thumb_url<S>(mut self, val: S) -> Self
|
pub fn thumb_url(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.thumb_url = Some(val);
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.thumb_url = Some(val.into());
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ pub struct InlineQueryResultDocument {
|
||||||
pub caption_entities: Option<Vec<MessageEntity>>,
|
pub caption_entities: Option<Vec<MessageEntity>>,
|
||||||
|
|
||||||
/// A valid URL for the file.
|
/// A valid URL for the file.
|
||||||
pub document_url: String,
|
pub document_url: reqwest::Url,
|
||||||
|
|
||||||
/// Mime type of the content of the file, either `application/pdf` or
|
/// Mime type of the content of the file, either `application/pdf` or
|
||||||
/// `application/zip`.
|
/// `application/zip`.
|
||||||
|
@ -53,7 +53,7 @@ pub struct InlineQueryResultDocument {
|
||||||
pub input_message_content: Option<InputMessageContent>,
|
pub input_message_content: Option<InputMessageContent>,
|
||||||
|
|
||||||
/// URL of the thumbnail (jpeg only) for the file.
|
/// URL of the thumbnail (jpeg only) for the file.
|
||||||
pub thumb_url: Option<String>,
|
pub thumb_url: Option<reqwest::Url>,
|
||||||
|
|
||||||
/// Thumbnail width.
|
/// Thumbnail width.
|
||||||
pub thumb_width: Option<i32>,
|
pub thumb_width: Option<i32>,
|
||||||
|
@ -87,7 +87,7 @@ impl InlineQueryResultDocument {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_mode<S>(mut self, val: ParseMode) -> Self {
|
pub fn parse_mode(mut self, val: ParseMode) -> Self {
|
||||||
self.parse_mode = Some(val);
|
self.parse_mode = Some(val);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -100,11 +100,8 @@ impl InlineQueryResultDocument {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn document_url<S>(mut self, val: S) -> Self
|
pub fn document_url(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.document_url = val;
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.document_url = val.into();
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,11 +128,8 @@ impl InlineQueryResultDocument {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thumb_url<S>(mut self, val: S) -> Self
|
pub fn thumb_url(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.thumb_url = Some(val);
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.thumb_url = Some(val.into());
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub struct InlineQueryResultGif {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
|
|
||||||
/// A valid URL for the GIF file. File size must not exceed 1MB.
|
/// A valid URL for the GIF file. File size must not exceed 1MB.
|
||||||
pub gif_url: String,
|
pub gif_url: reqwest::Url,
|
||||||
|
|
||||||
/// Width of the GIF.
|
/// Width of the GIF.
|
||||||
pub gif_width: Option<i32>,
|
pub gif_width: Option<i32>,
|
||||||
|
@ -28,7 +28,7 @@ pub struct InlineQueryResultGif {
|
||||||
pub gif_duration: Option<i32>,
|
pub gif_duration: Option<i32>,
|
||||||
|
|
||||||
/// URL of the static thumbnail for the result (jpeg or gif).
|
/// URL of the static thumbnail for the result (jpeg or gif).
|
||||||
pub thumb_url: String,
|
pub thumb_url: reqwest::Url,
|
||||||
|
|
||||||
/// Title for the result.
|
/// Title for the result.
|
||||||
pub title: Option<String>,
|
pub title: Option<String>,
|
||||||
|
@ -58,19 +58,17 @@ pub struct InlineQueryResultGif {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineQueryResultGif {
|
impl InlineQueryResultGif {
|
||||||
pub fn new<S1, S2, S3>(id: S1, gif_url: S2, thumb_url: S3) -> Self
|
pub fn new<S>(id: S, gif_url: reqwest::Url, thumb_url: reqwest::Url) -> Self
|
||||||
where
|
where
|
||||||
S1: Into<String>,
|
S: Into<String>,
|
||||||
S2: Into<String>,
|
|
||||||
S3: Into<String>,
|
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
gif_url: gif_url.into(),
|
gif_url,
|
||||||
gif_width: None,
|
gif_width: None,
|
||||||
gif_height: None,
|
gif_height: None,
|
||||||
gif_duration: None,
|
gif_duration: None,
|
||||||
thumb_url: thumb_url.into(),
|
thumb_url,
|
||||||
title: None,
|
title: None,
|
||||||
caption: None,
|
caption: None,
|
||||||
parse_mode: None,
|
parse_mode: None,
|
||||||
|
@ -88,11 +86,8 @@ impl InlineQueryResultGif {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gif_url<S>(mut self, val: S) -> Self
|
pub fn gif_url(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.gif_url = val;
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.gif_url = val.into();
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,11 +106,8 @@ impl InlineQueryResultGif {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thumb_url<S>(mut self, val: S) -> Self
|
pub fn thumb_url(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.thumb_url = val;
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.thumb_url = val.into();
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ pub struct InlineQueryResultLocation {
|
||||||
pub input_message_content: Option<InputMessageContent>,
|
pub input_message_content: Option<InputMessageContent>,
|
||||||
|
|
||||||
/// Url of the thumbnail for the result.
|
/// Url of the thumbnail for the result.
|
||||||
pub thumb_url: Option<String>,
|
pub thumb_url: Option<reqwest::Url>,
|
||||||
|
|
||||||
/// Thumbnail width.
|
/// Thumbnail width.
|
||||||
pub thumb_width: Option<u32>,
|
pub thumb_width: Option<u32>,
|
||||||
|
@ -137,11 +137,8 @@ impl InlineQueryResultLocation {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thumb_url<S>(mut self, val: S) -> Self
|
pub fn thumb_url<S>(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.thumb_url = Some(val);
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.thumb_url = Some(val.into());
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ pub struct InlineQueryResultMpeg4Gif {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
|
|
||||||
/// A valid URL for the MP4 file. File size must not exceed 1MB.
|
/// A valid URL for the MP4 file. File size must not exceed 1MB.
|
||||||
pub mpeg4_url: String,
|
pub mpeg4_url: reqwest::Url,
|
||||||
|
|
||||||
/// Video width.
|
/// Video width.
|
||||||
pub mpeg4_width: Option<i32>,
|
pub mpeg4_width: Option<i32>,
|
||||||
|
@ -29,7 +29,7 @@ pub struct InlineQueryResultMpeg4Gif {
|
||||||
pub mpeg4_duration: Option<i32>,
|
pub mpeg4_duration: Option<i32>,
|
||||||
|
|
||||||
/// URL of the static thumbnail (jpeg or gif) for the result.
|
/// URL of the static thumbnail (jpeg or gif) for the result.
|
||||||
pub thumb_url: String,
|
pub thumb_url: reqwest::Url,
|
||||||
|
|
||||||
/// Title for the result.
|
/// Title for the result.
|
||||||
pub title: Option<String>,
|
pub title: Option<String>,
|
||||||
|
@ -59,16 +59,14 @@ pub struct InlineQueryResultMpeg4Gif {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineQueryResultMpeg4Gif {
|
impl InlineQueryResultMpeg4Gif {
|
||||||
pub fn new<S1, S2, S3>(id: S1, mpeg4_url: S2, thumb_url: S3) -> Self
|
pub fn new<S>(id: S, mpeg4_url: reqwest::Url, thumb_url: reqwest::Url) -> Self
|
||||||
where
|
where
|
||||||
S1: Into<String>,
|
S: Into<String>,
|
||||||
S2: Into<String>,
|
|
||||||
S3: Into<String>,
|
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
mpeg4_url: mpeg4_url.into(),
|
mpeg4_url,
|
||||||
thumb_url: thumb_url.into(),
|
thumb_url,
|
||||||
mpeg4_width: None,
|
mpeg4_width: None,
|
||||||
mpeg4_height: None,
|
mpeg4_height: None,
|
||||||
mpeg4_duration: None,
|
mpeg4_duration: None,
|
||||||
|
@ -89,11 +87,8 @@ impl InlineQueryResultMpeg4Gif {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mpeg4_url<S>(mut self, val: S) -> Self
|
pub fn mpeg4_url(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.mpeg4_url = val;
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.mpeg4_url = val.into();
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,11 +107,8 @@ impl InlineQueryResultMpeg4Gif {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thumb_url<S>(mut self, val: S) -> Self
|
pub fn thumb_url(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.thumb_url = val;
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.thumb_url = val.into();
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +128,7 @@ impl InlineQueryResultMpeg4Gif {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_mode<S>(mut self, val: ParseMode) -> Self {
|
pub fn parse_mode(mut self, val: ParseMode) -> Self {
|
||||||
self.parse_mode = Some(val);
|
self.parse_mode = Some(val);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,10 @@ pub struct InlineQueryResultPhoto {
|
||||||
|
|
||||||
/// A valid URL of the photo. Photo must be in **jpeg** format. Photo size
|
/// A valid URL of the photo. Photo must be in **jpeg** format. Photo size
|
||||||
/// must not exceed 5MB.
|
/// must not exceed 5MB.
|
||||||
pub photo_url: String,
|
pub photo_url: reqwest::Url,
|
||||||
|
|
||||||
/// URL of the thumbnail for the photo.
|
/// URL of the thumbnail for the photo.
|
||||||
pub thumb_url: String,
|
pub thumb_url: reqwest::Url,
|
||||||
|
|
||||||
/// Width of the photo.
|
/// Width of the photo.
|
||||||
pub photo_width: Option<i32>,
|
pub photo_width: Option<i32>,
|
||||||
|
@ -59,16 +59,14 @@ pub struct InlineQueryResultPhoto {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineQueryResultPhoto {
|
impl InlineQueryResultPhoto {
|
||||||
pub fn new<S1, S2, S3>(id: S1, photo_url: S2, thumb_url: S3) -> Self
|
pub fn new<S>(id: S, photo_url: reqwest::Url, thumb_url: reqwest::Url) -> Self
|
||||||
where
|
where
|
||||||
S1: Into<String>,
|
S: Into<String>,
|
||||||
S2: Into<String>,
|
|
||||||
S3: Into<String>,
|
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
photo_url: photo_url.into(),
|
photo_url,
|
||||||
thumb_url: thumb_url.into(),
|
thumb_url,
|
||||||
photo_width: None,
|
photo_width: None,
|
||||||
photo_height: None,
|
photo_height: None,
|
||||||
title: None,
|
title: None,
|
||||||
|
@ -89,28 +87,22 @@ impl InlineQueryResultPhoto {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn photo_url<S>(mut self, val: S) -> Self
|
pub fn photo_url(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.photo_url = val;
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.photo_url = val.into();
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thumb_url<S>(mut self, val: S) -> Self
|
pub fn thumb_url<S>(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.thumb_url = val;
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.thumb_url = val.into();
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn photo_width<S>(mut self, val: i32) -> Self {
|
pub fn photo_width(mut self, val: i32) -> Self {
|
||||||
self.photo_width = Some(val);
|
self.photo_width = Some(val);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn photo_height<S>(mut self, val: i32) -> Self {
|
pub fn photo_height(mut self, val: i32) -> Self {
|
||||||
self.photo_height = Some(val);
|
self.photo_height = Some(val);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -139,7 +131,7 @@ impl InlineQueryResultPhoto {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_mode<S>(mut self, val: ParseMode) -> Self {
|
pub fn parse_mode(mut self, val: ParseMode) -> Self {
|
||||||
self.parse_mode = Some(val);
|
self.parse_mode = Some(val);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ pub struct InlineQueryResultVenue {
|
||||||
pub input_message_content: Option<InputMessageContent>,
|
pub input_message_content: Option<InputMessageContent>,
|
||||||
|
|
||||||
/// Url of the thumbnail for the result.
|
/// Url of the thumbnail for the result.
|
||||||
pub thumb_url: Option<String>,
|
pub thumb_url: Option<reqwest::Url>,
|
||||||
|
|
||||||
/// Thumbnail width.
|
/// Thumbnail width.
|
||||||
pub thumb_width: Option<i32>,
|
pub thumb_width: Option<i32>,
|
||||||
|
@ -162,11 +162,8 @@ impl InlineQueryResultVenue {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thumb_url<S>(mut self, val: S) -> Self
|
pub fn thumb_url(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.thumb_url = Some(val);
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.thumb_url = Some(val.into());
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,14 +18,14 @@ pub struct InlineQueryResultVideo {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
|
|
||||||
/// A valid URL for the embedded video player or video file.
|
/// A valid URL for the embedded video player or video file.
|
||||||
pub video_url: String,
|
pub video_url: reqwest::Url,
|
||||||
|
|
||||||
/// Mime type of the content of video url, `text/html` or `video/mp4`.
|
/// Mime type of the content of video url, `text/html` or `video/mp4`.
|
||||||
#[serde(with = "crate::types::non_telegram_types::mime::deser")]
|
#[serde(with = "crate::types::non_telegram_types::mime::deser")]
|
||||||
pub mime_type: Mime,
|
pub mime_type: Mime,
|
||||||
|
|
||||||
/// URL of the thumbnail (jpeg only) for the video.
|
/// URL of the thumbnail (jpeg only) for the video.
|
||||||
pub thumb_url: String,
|
pub thumb_url: reqwest::Url,
|
||||||
|
|
||||||
/// Title for the result.
|
/// Title for the result.
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
@ -72,24 +72,22 @@ pub struct InlineQueryResultVideo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineQueryResultVideo {
|
impl InlineQueryResultVideo {
|
||||||
pub fn new<S1, S2, S3, S4>(
|
pub fn new<S1, S2>(
|
||||||
id: S1,
|
id: S1,
|
||||||
video_url: S2,
|
video_url: reqwest::Url,
|
||||||
mime_type: Mime,
|
mime_type: Mime,
|
||||||
thumb_url: S3,
|
thumb_url: reqwest::Url,
|
||||||
title: S4,
|
title: S2,
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
S1: Into<String>,
|
S1: Into<String>,
|
||||||
S2: Into<String>,
|
S2: Into<String>,
|
||||||
S3: Into<String>,
|
|
||||||
S4: Into<String>,
|
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
video_url: video_url.into(),
|
video_url,
|
||||||
mime_type,
|
mime_type,
|
||||||
thumb_url: thumb_url.into(),
|
thumb_url,
|
||||||
title: title.into(),
|
title: title.into(),
|
||||||
caption: None,
|
caption: None,
|
||||||
parse_mode: None,
|
parse_mode: None,
|
||||||
|
@ -111,11 +109,8 @@ impl InlineQueryResultVideo {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn video_url<S>(mut self, val: S) -> Self
|
pub fn video_url(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.video_url = val;
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.video_url = val.into();
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,11 +119,8 @@ impl InlineQueryResultVideo {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thumb_url<S>(mut self, val: S) -> Self
|
pub fn thumb_url(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.thumb_url = val;
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.thumb_url = val.into();
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ pub struct InlineQueryResultVoice {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
|
|
||||||
/// A valid URL for the voice recording.
|
/// A valid URL for the voice recording.
|
||||||
pub voice_url: String,
|
pub voice_url: reqwest::Url,
|
||||||
|
|
||||||
/// Recording title.
|
/// Recording title.
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
@ -50,15 +50,14 @@ pub struct InlineQueryResultVoice {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineQueryResultVoice {
|
impl InlineQueryResultVoice {
|
||||||
pub fn new<S1, S2, S3>(id: S1, voice_url: S2, title: S3) -> Self
|
pub fn new<S1, S2>(id: S1, voice_url: reqwest::Url, title: S2) -> Self
|
||||||
where
|
where
|
||||||
S1: Into<String>,
|
S1: Into<String>,
|
||||||
S2: Into<String>,
|
S2: Into<String>,
|
||||||
S3: Into<String>,
|
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
voice_url: voice_url.into(),
|
voice_url,
|
||||||
title: title.into(),
|
title: title.into(),
|
||||||
caption: None,
|
caption: None,
|
||||||
parse_mode: None,
|
parse_mode: None,
|
||||||
|
@ -77,11 +76,8 @@ impl InlineQueryResultVoice {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn voice_url<S>(mut self, val: S) -> Self
|
pub fn voice_url(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.voice_url = val;
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.voice_url = val.into();
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use reqwest::Url;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use std::{borrow::Cow, path::PathBuf};
|
use std::{borrow::Cow, path::PathBuf};
|
||||||
|
@ -13,7 +14,7 @@ pub enum InputFile {
|
||||||
file_name: String,
|
file_name: String,
|
||||||
data: Cow<'static, [u8]>,
|
data: Cow<'static, [u8]>,
|
||||||
},
|
},
|
||||||
Url(String),
|
Url(Url),
|
||||||
FileId(String),
|
FileId(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,11 +37,8 @@ impl InputFile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn url<T>(url: T) -> Self
|
pub fn url(url: Url) -> Self {
|
||||||
where
|
Self::Url(url)
|
||||||
T: Into<String>,
|
|
||||||
{
|
|
||||||
Self::Url(url.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_id<T>(file_id: T) -> Self
|
pub fn file_id<T>(file_id: T) -> Self
|
||||||
|
@ -57,7 +55,7 @@ impl InputFile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_url(&self) -> Option<&String> {
|
pub fn as_url(&self) -> Option<&Url> {
|
||||||
match self {
|
match self {
|
||||||
Self::Url(url) => Some(url),
|
Self::Url(url) => Some(url),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -118,7 +116,8 @@ impl InputFile {
|
||||||
Ok(Part::stream(Body::wrap_stream(file)).file_name(file_name))
|
Ok(Part::stream(Body::wrap_stream(file)).file_name(file_name))
|
||||||
}
|
}
|
||||||
Self::Memory { file_name, data } => Ok(Part::bytes(data).file_name(file_name)),
|
Self::Memory { file_name, data } => Ok(Part::bytes(data).file_name(file_name)),
|
||||||
Self::Url(s) | Self::FileId(s) => Ok(Part::text(s)),
|
Self::Url(s) => Ok(Part::text(String::from(s))),
|
||||||
|
Self::FileId(s) => Ok(Part::text(s)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,18 +15,39 @@ use serde::{Deserialize, Serialize};
|
||||||
#[serde_with_macros::skip_serializing_none]
|
#[serde_with_macros::skip_serializing_none]
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct LoginUrl {
|
pub struct LoginUrl {
|
||||||
pub url: String,
|
/// An HTTP URL to be opened with user authorization data added to the query
|
||||||
|
/// string when the button is pressed. If the user refuses to provide
|
||||||
|
/// authorization data, the original URL without information about the user
|
||||||
|
/// will be opened. The data added is the same as described in [Receiving
|
||||||
|
/// authorization data].
|
||||||
|
///
|
||||||
|
/// [Receiving authorization data]: https://core.telegram.org/widgets/login#receiving-authorization-data
|
||||||
|
///
|
||||||
|
/// NOTE: You must always check the hash of the received data to verify the
|
||||||
|
/// authentication and the integrity of the data as described in [Checking
|
||||||
|
/// authorization].
|
||||||
|
///
|
||||||
|
/// [Checking authorization]: https://core.telegram.org/widgets/login#checking-authorization
|
||||||
|
pub url: reqwest::Url,
|
||||||
|
/// New text of the button in forwarded messages.
|
||||||
pub forward_text: Option<String>,
|
pub forward_text: Option<String>,
|
||||||
|
/// Username of a bot, which will be used for user authorization. See
|
||||||
|
/// [Setting up a bot] for more details. If not specified, the current bot's
|
||||||
|
/// username will be assumed. The url's domain must be the same as the
|
||||||
|
/// domain linked with the bot. See [Linking your domain to the bot] for
|
||||||
|
/// more details.
|
||||||
|
///
|
||||||
|
/// [Setting up a bot]: https://core.telegram.org/widgets/login#setting-up-a-bot
|
||||||
|
/// [Linking your domain to the bot]: https://core.telegram.org/widgets/login#linking-your-domain-to-the-bot
|
||||||
pub bot_username: Option<String>,
|
pub bot_username: Option<String>,
|
||||||
|
/// Pass `true` to request the permission for your bot to send messages to
|
||||||
|
/// the user.
|
||||||
pub request_write_access: Option<bool>,
|
pub request_write_access: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LoginUrl {
|
impl LoginUrl {
|
||||||
pub fn url<S>(mut self, val: S) -> Self
|
pub fn url(mut self, val: reqwest::Url) -> Self {
|
||||||
where
|
self.url = val;
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.url = val.into();
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +67,7 @@ impl LoginUrl {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_write_access<S>(mut self, val: bool) -> Self {
|
pub fn request_write_access(mut self, val: bool) -> Self {
|
||||||
self.request_write_access = Some(val);
|
self.request_write_access = Some(val);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#![allow(clippy::large_enum_variant)]
|
#![allow(clippy::large_enum_variant)]
|
||||||
|
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
|
@ -19,7 +20,8 @@ pub struct Message {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
|
|
||||||
/// Date the message was sent in Unix time.
|
/// Date the message was sent in Unix time.
|
||||||
pub date: i32,
|
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
|
||||||
|
pub date: DateTime<Utc>,
|
||||||
|
|
||||||
/// Conversation the message belongs to.
|
/// Conversation the message belongs to.
|
||||||
pub chat: Chat,
|
pub chat: Chat,
|
||||||
|
@ -78,7 +80,9 @@ pub struct MessageCommon {
|
||||||
pub forward_kind: ForwardKind,
|
pub forward_kind: ForwardKind,
|
||||||
|
|
||||||
/// Date the message was last edited in Unix time.
|
/// Date the message was last edited in Unix time.
|
||||||
pub edit_date: Option<i32>,
|
#[serde(with = "crate::types::serde_opt_date_from_unix_timestamp")]
|
||||||
|
#[serde(default = "crate::types::serde_opt_date_from_unix_timestamp::none")]
|
||||||
|
pub edit_date: Option<DateTime<Utc>>,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub media_kind: MediaKind,
|
pub media_kind: MediaKind,
|
||||||
|
@ -234,7 +238,8 @@ pub enum ForwardKind {
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct ForwardChannel {
|
pub struct ForwardChannel {
|
||||||
#[serde(rename = "forward_date")]
|
#[serde(rename = "forward_date")]
|
||||||
pub date: i32,
|
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
|
||||||
|
pub date: DateTime<Utc>,
|
||||||
|
|
||||||
#[serde(rename = "forward_from_chat")]
|
#[serde(rename = "forward_from_chat")]
|
||||||
pub chat: Chat,
|
pub chat: Chat,
|
||||||
|
@ -249,7 +254,8 @@ pub struct ForwardChannel {
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct ForwardNonChannel {
|
pub struct ForwardNonChannel {
|
||||||
#[serde(rename = "forward_date")]
|
#[serde(rename = "forward_date")]
|
||||||
pub date: i32,
|
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
|
||||||
|
pub date: DateTime<Utc>,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub from: ForwardedFrom,
|
pub from: ForwardedFrom,
|
||||||
|
@ -480,6 +486,7 @@ pub struct MessageVoiceChatParticipantsInvited {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod getters {
|
mod getters {
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
|
@ -570,7 +577,7 @@ mod getters {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn forward_date(&self) -> Option<&i32> {
|
pub fn forward_date(&self) -> Option<&DateTime<Utc>> {
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
Common(MessageCommon {
|
Common(MessageCommon {
|
||||||
forward_kind: ForwardKind::Channel(ForwardChannel { date, .. }),
|
forward_kind: ForwardKind::Channel(ForwardChannel { date, .. }),
|
||||||
|
@ -597,7 +604,7 @@ mod getters {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn edit_date(&self) -> Option<&i32> {
|
pub fn edit_date(&self) -> Option<&DateTime<Utc>> {
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
Common(MessageCommon { edit_date, .. }) => edit_date.as_ref(),
|
Common(MessageCommon { edit_date, .. }) => edit_date.as_ref(),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
|
@ -59,7 +59,7 @@ pub enum MessageEntityKind {
|
||||||
Italic,
|
Italic,
|
||||||
Code,
|
Code,
|
||||||
Pre { language: Option<String> },
|
Pre { language: Option<String> },
|
||||||
TextLink { url: String },
|
TextLink { url: reqwest::Url },
|
||||||
TextMention { user: User },
|
TextMention { user: User },
|
||||||
Underline,
|
Underline,
|
||||||
Strikethrough,
|
Strikethrough,
|
||||||
|
@ -76,13 +76,13 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
MessageEntity {
|
MessageEntity {
|
||||||
kind: MessageEntityKind::TextLink {
|
kind: MessageEntityKind::TextLink {
|
||||||
url: "ya.ru".into()
|
url: reqwest::Url::parse("https://example.com").unwrap(),
|
||||||
},
|
},
|
||||||
offset: 1,
|
offset: 1,
|
||||||
length: 2,
|
length: 2,
|
||||||
},
|
},
|
||||||
from_str::<MessageEntity>(
|
from_str::<MessageEntity>(
|
||||||
r#"{"type":"text_link","url":"ya.ru","offset":1,"length":2}"#
|
r#"{"type":"text_link","url":"https://example.com","offset":1,"length":2}"#
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
);
|
);
|
||||||
|
@ -100,10 +100,8 @@ mod tests {
|
||||||
offset: 1,
|
offset: 1,
|
||||||
length: 2,
|
length: 2,
|
||||||
},
|
},
|
||||||
from_str::<MessageEntity>(
|
from_str::<MessageEntity>(r#"{"type":"pre","offset":1,"length":2,"language":"rust"}"#)
|
||||||
r#"{"type":"pre","url":"ya.ru","offset":1,"length":2,"language":"rust"}"#
|
.unwrap()
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// This object represents a file uploaded to Telegram Passport.
|
/// This object represents a file uploaded to Telegram Passport.
|
||||||
|
@ -19,6 +20,7 @@ pub struct PassportFile {
|
||||||
/// File size.
|
/// File size.
|
||||||
pub file_size: u64,
|
pub file_size: u64,
|
||||||
|
|
||||||
/// Unix time when the file was uploaded.
|
/// Time when the file was uploaded.
|
||||||
pub file_date: u64,
|
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
|
||||||
|
pub file_date: DateTime<Utc>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use crate::types::{MessageEntity, PollType};
|
use crate::types::{MessageEntity, PollType};
|
||||||
|
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// This object contains information about a poll.
|
/// This object contains information about a poll.
|
||||||
|
@ -48,9 +50,10 @@ pub struct Poll {
|
||||||
/// Amount of time in seconds the poll will be active after creation.
|
/// Amount of time in seconds the poll will be active after creation.
|
||||||
pub open_period: Option<i32>,
|
pub open_period: Option<i32>,
|
||||||
|
|
||||||
/// Point in time (Unix timestamp) when the poll will be automatically
|
/// Point in time when the poll will be automatically closed.
|
||||||
/// closed.
|
#[serde(with = "crate::types::serde_opt_date_from_unix_timestamp")]
|
||||||
pub close_date: Option<i32>,
|
#[serde(default = "crate::types::serde_opt_date_from_unix_timestamp::none")]
|
||||||
|
pub close_date: Option<DateTime<Utc>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This object contains information about one answer option in a poll.
|
/// This object contains information about one answer option in a poll.
|
||||||
|
|
|
@ -144,9 +144,14 @@ mod test {
|
||||||
MessageCommon, MessageKind, Update, UpdateKind, User,
|
MessageCommon, MessageKind, Update, UpdateKind, User,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||||
|
|
||||||
// TODO: more tests for deserialization
|
// TODO: more tests for deserialization
|
||||||
#[test]
|
#[test]
|
||||||
fn message() {
|
fn message() {
|
||||||
|
let timestamp = 1_569_518_342;
|
||||||
|
let date = DateTime::from_utc(NaiveDateTime::from_timestamp(timestamp, 0), Utc);
|
||||||
|
|
||||||
let json = r#"{
|
let json = r#"{
|
||||||
"update_id":892252934,
|
"update_id":892252934,
|
||||||
"message":{
|
"message":{
|
||||||
|
@ -174,7 +179,7 @@ mod test {
|
||||||
kind: UpdateKind::Message(Message {
|
kind: UpdateKind::Message(Message {
|
||||||
via_bot: None,
|
via_bot: None,
|
||||||
id: 6557,
|
id: 6557,
|
||||||
date: 1_569_518_342,
|
date,
|
||||||
chat: Chat {
|
chat: Chat {
|
||||||
id: 218_485_655,
|
id: 218_485_655,
|
||||||
kind: ChatKind::Private(ChatPrivate {
|
kind: ChatKind::Private(ChatPrivate {
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// This object represents a service message about a voice chat scheduled in the
|
/// This object represents a service message about a voice chat scheduled in the
|
||||||
/// chat.
|
/// chat.
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct VoiceChatScheduled {
|
pub struct VoiceChatScheduled {
|
||||||
/// Point in time (Unix timestamp) when the voice chat is supposed to be
|
/// Point in time when the voice chat is supposed to be started by a chat
|
||||||
/// started by a chat administrator.
|
/// administrator.
|
||||||
pub start_date: u64,
|
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
|
||||||
|
pub start_date: DateTime<Utc>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Contains information about the current status of a webhook.
|
/// Contains information about the current status of a webhook.
|
||||||
|
@ -6,8 +7,8 @@ use serde::{Deserialize, Serialize};
|
||||||
#[serde_with_macros::skip_serializing_none]
|
#[serde_with_macros::skip_serializing_none]
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct WebhookInfo {
|
pub struct WebhookInfo {
|
||||||
/// Webhook URL, may be empty if webhook is not set up.
|
/// Webhook URL, `None` if webhook is not set up.
|
||||||
pub url: String,
|
pub url: Option<reqwest::Url>,
|
||||||
|
|
||||||
/// `true`, if a custom certificate was provided for webhook certificate
|
/// `true`, if a custom certificate was provided for webhook certificate
|
||||||
/// checks.
|
/// checks.
|
||||||
|
@ -19,9 +20,11 @@ pub struct WebhookInfo {
|
||||||
/// Currently used webhook IP address.
|
/// Currently used webhook IP address.
|
||||||
pub ip_address: Option<String>,
|
pub ip_address: Option<String>,
|
||||||
|
|
||||||
/// Unix time for the most recent error that happened when trying to
|
/// Time of the most recent error that happened when trying to
|
||||||
/// deliver an update via webhook.
|
/// deliver an update via webhook.
|
||||||
pub last_error_date: Option<u64>,
|
#[serde(with = "crate::types::serde_opt_date_from_unix_timestamp")]
|
||||||
|
#[serde(default = "crate::types::serde_opt_date_from_unix_timestamp::none")]
|
||||||
|
pub last_error_date: Option<DateTime<Utc>>,
|
||||||
|
|
||||||
/// Error message in human-readable format for the most recent error that
|
/// Error message in human-readable format for the most recent error that
|
||||||
/// happened when trying to deliver an update via webhook.
|
/// happened when trying to deliver an update via webhook.
|
||||||
|
|
Loading…
Reference in a new issue