mirror of
https://github.com/teloxide/teloxide.git
synced 2025-01-09 11:43:57 +01:00
Merge branch 'dev' into dispatcher
This commit is contained in:
commit
f8f133edea
60 changed files with 2092 additions and 772 deletions
18
Cargo.toml
18
Cargo.toml
|
@ -6,16 +6,20 @@ edition = "2018"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
reqwest = { git = "https://github.com/seanmonstar/reqwest", rev = "ba7b2a754eab0d79817ea8551d0803806ae8af7d" }
|
reqwest = { version = "0.10.0-alpha.1", features = ["json", "unstable-stream"] }
|
||||||
serde_json = "1.0.39"
|
serde_json = "1.0.41"
|
||||||
serde = {version = "1.0.92", features = ["derive"] }
|
serde = { version = "1.0.101", features = ["derive"] }
|
||||||
lazy_static = "1.3"
|
|
||||||
apply = "0.2.2"
|
apply = "0.2.2"
|
||||||
derive_more = "0.15.0"
|
derive_more = "0.15.0"
|
||||||
tokio = "0.2.0-alpha.4"
|
tokio = "0.2.0-alpha.6"
|
||||||
bytes = "0.4.12"
|
bytes = "0.4.12"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
futures-preview = "0.3.0-alpha.18"
|
|
||||||
pin-project = "0.4.0-alpha.7"
|
pin-project = "0.4.0-alpha.7"
|
||||||
|
futures-preview = "0.3.0-alpha.19"
|
||||||
async-trait = "0.1.13"
|
async-trait = "0.1.13"
|
||||||
libc = "0.2.62"
|
thiserror = "1.0.2"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
|
||||||
|
unstable-stream = [] # add streams to public API
|
BIN
ICON.jpg
Normal file
BIN
ICON.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
26
README.md
26
README.md
|
@ -1,12 +1,30 @@
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<h1>async-telegram-bot</h1>
|
<h1>async-telegram-bot</h1>
|
||||||
|
|
||||||
|
<a href="https://docs.rs/async-telegram-bot/">
|
||||||
|
<img src="https://img.shields.io/badge/docs.rs-link-blue.svg">
|
||||||
|
</a>
|
||||||
<a href="https://travis-ci.com/async-telegram-bot/async-telegram-bot">
|
<a href="https://travis-ci.com/async-telegram-bot/async-telegram-bot">
|
||||||
<img src="https://travis-ci.com/async-telegram-bot/async-telegram-bot.svg?branch=dev" />
|
<img src="https://travis-ci.com/async-telegram-bot/async-telegram-bot.svg?branch=dev" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
<a href="LICENSE">
|
||||||
|
<img src="https://img.shields.io/badge/license-MIT-blue.svg">
|
||||||
|
</a>
|
||||||
|
<a href="https://crates.io/crates/async-telegram-bot">
|
||||||
|
<img src="https://img.shields.io/badge/crates.io-v0.1.0-orange.svg">
|
||||||
|
</a>
|
||||||
|
|
||||||
## Dependency graph
|
<br>
|
||||||
<div align="center">
|
<img src="ICON.jpg" width="300"/>
|
||||||
<img src="https://github.com/async-telegram-bot/async-telegram-bot/blob/dev/graph.png" />
|
<br>
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet consectetur adipiscing elit nibh cubilia, nostra ultricies class torquent integer scelerisque netus euismod vehicula, metus aliquam morbi leo risus cursus massa potenti.
|
||||||
|
|
||||||
|
<h4>
|
||||||
|
<a href="https://github.com/async-telegram-bot/async-telegram-bot/pulse">Pulse</a> ·
|
||||||
|
<a href="https://github.com/async-telegram-bot/async-telegram-bot/stargazers">Stargazers</a> ·
|
||||||
|
<a href="https://github.com/async-telegram-bot/async-telegram-bot/releases">Releases</a> ·
|
||||||
|
<a href="https://github.com/async-telegram-bot/async-telegram-bot/blob/master/CONTRIBUTING.md">Contributing</a>
|
||||||
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
|
|
BIN
graph.png
BIN
graph.png
Binary file not shown.
Before Width: | Height: | Size: 2.7 MiB |
212
src/bot/api.rs
212
src/bot/api.rs
|
@ -1,11 +1,14 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
bot::Bot,
|
bot::Bot,
|
||||||
requests::{
|
requests::{
|
||||||
ChatId, EditMessageLiveLocation, ForwardMessage, GetFile, GetMe,
|
AnswerPreCheckoutQuery, AnswerShippingQuery, EditMessageLiveLocation,
|
||||||
SendAudio, SendLocation, SendMediaGroup, SendMessage, SendPhoto,
|
ForwardMessage, GetFile, GetMe, KickChatMember, PinChatMessage,
|
||||||
StopMessageLiveLocation, GetUpdates
|
PromoteChatMember, RestrictChatMember, SendAudio, SendChatAction,
|
||||||
|
SendContact, SendLocation, SendMediaGroup, SendMessage, SendPhoto,
|
||||||
|
SendPoll, SendVenue, SendVideoNote, SendVoice, StopMessageLiveLocation,
|
||||||
|
UnbanChatMember, UnpinChatMessage, GetUpdates
|
||||||
},
|
},
|
||||||
types::{InputFile, InputMedia},
|
types::{ChatAction, ChatId, ChatPermissions, InputFile, InputMedia},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Telegram functions
|
/// Telegram functions
|
||||||
|
@ -23,7 +26,7 @@ impl Bot {
|
||||||
C: Into<ChatId>,
|
C: Into<ChatId>,
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
SendMessage::new(self.ctx(), chat_id.into(), text.into())
|
SendMessage::new(self.ctx(), chat_id, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn edit_message_live_location<Lt, Lg>(
|
pub fn edit_message_live_location<Lt, Lg>(
|
||||||
|
@ -35,11 +38,7 @@ impl Bot {
|
||||||
Lt: Into<f64>,
|
Lt: Into<f64>,
|
||||||
Lg: Into<f64>,
|
Lg: Into<f64>,
|
||||||
{
|
{
|
||||||
EditMessageLiveLocation::new(
|
EditMessageLiveLocation::new(self.ctx(), latitude, longitude)
|
||||||
self.ctx(),
|
|
||||||
latitude.into(),
|
|
||||||
longitude.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn forward_message<C, F, M>(
|
pub fn forward_message<C, F, M>(
|
||||||
|
@ -53,12 +52,7 @@ impl Bot {
|
||||||
F: Into<ChatId>,
|
F: Into<ChatId>,
|
||||||
M: Into<i32>,
|
M: Into<i32>,
|
||||||
{
|
{
|
||||||
ForwardMessage::new(
|
ForwardMessage::new(self.ctx(), chat_id, from_chat_id, message_id)
|
||||||
self.ctx(),
|
|
||||||
chat_id.into(),
|
|
||||||
from_chat_id.into(),
|
|
||||||
message_id.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_audio<C, A>(&self, chat_id: C, audio: A) -> SendAudio
|
pub fn send_audio<C, A>(&self, chat_id: C, audio: A) -> SendAudio
|
||||||
|
@ -66,7 +60,7 @@ impl Bot {
|
||||||
C: Into<ChatId>,
|
C: Into<ChatId>,
|
||||||
A: Into<InputFile>,
|
A: Into<InputFile>,
|
||||||
{
|
{
|
||||||
SendAudio::new(self.ctx(), chat_id.into(), audio.into())
|
SendAudio::new(self.ctx(), chat_id, audio)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_location<C, Lt, Lg>(
|
pub fn send_location<C, Lt, Lg>(
|
||||||
|
@ -80,12 +74,7 @@ impl Bot {
|
||||||
Lt: Into<f64>,
|
Lt: Into<f64>,
|
||||||
Lg: Into<f64>,
|
Lg: Into<f64>,
|
||||||
{
|
{
|
||||||
SendLocation::new(
|
SendLocation::new(self.ctx(), chat_id, latitude, longitude)
|
||||||
self.ctx(),
|
|
||||||
chat_id.into(),
|
|
||||||
latitude.into(),
|
|
||||||
longitude.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_media_group<C, M>(&self, chat_id: C, media: M) -> SendMediaGroup
|
pub fn send_media_group<C, M>(&self, chat_id: C, media: M) -> SendMediaGroup
|
||||||
|
@ -93,7 +82,7 @@ impl Bot {
|
||||||
C: Into<ChatId>,
|
C: Into<ChatId>,
|
||||||
M: Into<Vec<InputMedia>>,
|
M: Into<Vec<InputMedia>>,
|
||||||
{
|
{
|
||||||
SendMediaGroup::new(self.ctx(), chat_id.into(), media.into())
|
SendMediaGroup::new(self.ctx(), chat_id, media)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_photo<C, P>(&self, chat_id: C, photo: P) -> SendPhoto
|
pub fn send_photo<C, P>(&self, chat_id: C, photo: P) -> SendPhoto
|
||||||
|
@ -101,7 +90,7 @@ impl Bot {
|
||||||
C: Into<ChatId>,
|
C: Into<ChatId>,
|
||||||
P: Into<InputFile>,
|
P: Into<InputFile>,
|
||||||
{
|
{
|
||||||
SendPhoto::new(self.ctx(), chat_id.into(), photo.into())
|
SendPhoto::new(self.ctx(), chat_id, photo)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop_message_live_location(&self) -> StopMessageLiveLocation {
|
pub fn stop_message_live_location(&self) -> StopMessageLiveLocation {
|
||||||
|
@ -112,6 +101,177 @@ impl Bot {
|
||||||
where
|
where
|
||||||
F: Into<String>,
|
F: Into<String>,
|
||||||
{
|
{
|
||||||
GetFile::new(self.ctx(), file_id.into())
|
GetFile::new(self.ctx(), file_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn answer_pre_checkout_query<I, O>(
|
||||||
|
&self,
|
||||||
|
pre_checkout_query_id: I,
|
||||||
|
ok: O,
|
||||||
|
) -> AnswerPreCheckoutQuery
|
||||||
|
where
|
||||||
|
I: Into<String>,
|
||||||
|
O: Into<bool>,
|
||||||
|
{
|
||||||
|
AnswerPreCheckoutQuery::new(self.ctx(), pre_checkout_query_id, ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn answer_shipping_query<I, O>(
|
||||||
|
&self,
|
||||||
|
shipping_query_id: I,
|
||||||
|
ok: O,
|
||||||
|
) -> AnswerShippingQuery
|
||||||
|
where
|
||||||
|
I: Into<String>,
|
||||||
|
O: Into<bool>,
|
||||||
|
{
|
||||||
|
AnswerShippingQuery::new(self.ctx(), shipping_query_id, ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kick_chat_member<C, U>(
|
||||||
|
&self,
|
||||||
|
chat_id: C,
|
||||||
|
user_id: U,
|
||||||
|
) -> KickChatMember
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
U: Into<i32>,
|
||||||
|
{
|
||||||
|
KickChatMember::new(self.ctx(), chat_id, user_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pin_chat_message<C, M>(
|
||||||
|
&self,
|
||||||
|
chat_id: C,
|
||||||
|
message_id: M,
|
||||||
|
) -> PinChatMessage
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
M: Into<i32>,
|
||||||
|
{
|
||||||
|
PinChatMessage::new(self.ctx(), chat_id, message_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn promote_chat_member<C, U>(
|
||||||
|
&self,
|
||||||
|
chat_id: C,
|
||||||
|
user_id: U,
|
||||||
|
) -> PromoteChatMember
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
U: Into<i32>,
|
||||||
|
{
|
||||||
|
PromoteChatMember::new(self.ctx(), chat_id, user_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn restrict_chat_member<C, U, P>(
|
||||||
|
&self,
|
||||||
|
chat_id: C,
|
||||||
|
user_id: U,
|
||||||
|
permissions: P,
|
||||||
|
) -> RestrictChatMember
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
U: Into<i32>,
|
||||||
|
P: Into<ChatPermissions>,
|
||||||
|
{
|
||||||
|
RestrictChatMember::new(self.ctx(), chat_id, user_id, permissions)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_chat_action<C, A>(
|
||||||
|
&self,
|
||||||
|
chat_id: C,
|
||||||
|
action: A,
|
||||||
|
) -> SendChatAction
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
A: Into<ChatAction>,
|
||||||
|
{
|
||||||
|
SendChatAction::new(self.ctx(), chat_id, action)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_contact<C, P, F>(
|
||||||
|
&self,
|
||||||
|
chat_id: C,
|
||||||
|
phone_number: P,
|
||||||
|
first_name: F,
|
||||||
|
) -> SendContact
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
P: Into<String>,
|
||||||
|
F: Into<String>,
|
||||||
|
{
|
||||||
|
SendContact::new(self.ctx(), chat_id, phone_number, first_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_poll<C, Q, O>(
|
||||||
|
&self,
|
||||||
|
chat_id: C,
|
||||||
|
question: Q,
|
||||||
|
options: O,
|
||||||
|
) -> SendPoll
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
Q: Into<String>,
|
||||||
|
O: Into<Vec<String>>,
|
||||||
|
{
|
||||||
|
SendPoll::new(self.ctx(), chat_id, question, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_venue<C, Lt, Lg, T, A>(
|
||||||
|
&self,
|
||||||
|
chat_id: C,
|
||||||
|
latitude: Lt,
|
||||||
|
longitude: Lg,
|
||||||
|
title: T,
|
||||||
|
address: A,
|
||||||
|
) -> SendVenue
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
Lt: Into<f64>,
|
||||||
|
Lg: Into<f64>,
|
||||||
|
T: Into<String>,
|
||||||
|
A: Into<String>,
|
||||||
|
{
|
||||||
|
SendVenue::new(self.ctx(), chat_id, latitude, longitude, title, address)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_video_note<C, V>(
|
||||||
|
&self,
|
||||||
|
chat_id: C,
|
||||||
|
video_note: V,
|
||||||
|
) -> SendVideoNote
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
V: Into<String>, // TODO: InputFile
|
||||||
|
{
|
||||||
|
SendVideoNote::new(self.ctx(), chat_id, video_note)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_voice<C, V>(&self, chat_id: C, voice: V) -> SendVoice
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
V: Into<String>, // TODO: InputFile
|
||||||
|
{
|
||||||
|
SendVoice::new(self.ctx(), chat_id, voice)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unban_chat_member<C, U>(
|
||||||
|
&self,
|
||||||
|
chat_id: C,
|
||||||
|
user_id: U,
|
||||||
|
) -> UnbanChatMember
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
U: Into<i32>,
|
||||||
|
{
|
||||||
|
UnbanChatMember::new(self.ctx(), chat_id, user_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unpin_chat_message<C>(&self, chat_id: C) -> UnpinChatMessage
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
{
|
||||||
|
UnpinChatMessage::new(self.ctx(), chat_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use reqwest::r#async::Chunk;
|
use tokio::io::AsyncWrite;
|
||||||
use tokio::{io::AsyncWrite, stream::Stream};
|
|
||||||
|
|
||||||
use crate::{
|
#[cfg(feature = "unstable-stream")]
|
||||||
bot::Bot,
|
use ::{bytes::Bytes, tokio::stream::Stream};
|
||||||
network::{download_file, download_file_stream},
|
|
||||||
DownloadError,
|
#[cfg(feature = "unstable-stream")]
|
||||||
};
|
use crate::network::download_file_stream;
|
||||||
|
use crate::{bot::Bot, network::download_file, DownloadError};
|
||||||
|
|
||||||
impl Bot {
|
impl Bot {
|
||||||
/// Download file from telegram into `destination`.
|
/// Download file from telegram into `destination`.
|
||||||
|
@ -26,8 +26,7 @@ impl Bot {
|
||||||
/// let bot = Bot::new("TOKEN");
|
/// let bot = Bot::new("TOKEN");
|
||||||
/// let mut file = File::create("/home/waffle/Pictures/test.png").await?;
|
/// let mut file = File::create("/home/waffle/Pictures/test.png").await?;
|
||||||
///
|
///
|
||||||
/// let TgFile { file_path, .. } =
|
/// let TgFile { file_path, .. } = bot.get_file("*file_id*").send().await?;
|
||||||
/// bot.get_file("*file_id*").send_boxed().await?;
|
|
||||||
/// bot.download_file(&file_path, &mut file).await?;
|
/// bot.download_file(&file_path, &mut file).await?;
|
||||||
/// # Ok(()) }
|
/// # Ok(()) }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -56,10 +55,11 @@ impl Bot {
|
||||||
/// [`AsyncWrite`]: tokio::io::AsyncWrite
|
/// [`AsyncWrite`]: tokio::io::AsyncWrite
|
||||||
/// [`tokio::fs::File`]: tokio::fs::File
|
/// [`tokio::fs::File`]: tokio::fs::File
|
||||||
/// [`download_file`]: crate::bot::Bot::download_file
|
/// [`download_file`]: crate::bot::Bot::download_file
|
||||||
|
#[cfg(feature = "unstable-stream")]
|
||||||
pub async fn download_file_stream(
|
pub async fn download_file_stream(
|
||||||
&self,
|
&self,
|
||||||
path: &str,
|
path: &str,
|
||||||
) -> Result<impl Stream<Item = Result<Chunk, reqwest::Error>>, reqwest::Error>
|
) -> Result<impl Stream<Item = Result<Bytes, reqwest::Error>>, reqwest::Error>
|
||||||
{
|
{
|
||||||
download_file_stream(&self.client, &self.token, path).await
|
download_file_stream(&self.client, &self.token, path).await
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use reqwest::r#async::Client;
|
use reqwest::Client;
|
||||||
|
|
||||||
use crate::requests::RequestContext;
|
use crate::requests::RequestContext;
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,21 @@
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
|
|
||||||
//<editor-fold desc="download">
|
//<editor-fold desc="download">
|
||||||
#[derive(Debug, Display, From)]
|
#[derive(Debug, Error, From)]
|
||||||
pub enum DownloadError {
|
pub enum DownloadError {
|
||||||
#[display(fmt = "Network error: {err}", err = _0)]
|
#[error("A network error: {0}")]
|
||||||
NetworkError(reqwest::Error),
|
NetworkError(#[source] reqwest::Error),
|
||||||
|
|
||||||
#[display(fmt = "IO Error: {err}", err = _0)]
|
#[error("An I/O error: {0}")]
|
||||||
Io(std::io::Error),
|
Io(#[source] std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::Error for DownloadError {
|
|
||||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
|
||||||
match self {
|
|
||||||
DownloadError::NetworkError(err) => Some(err),
|
|
||||||
DownloadError::Io(err) => Some(err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
|
|
||||||
//<editor-fold desc="request">
|
//<editor-fold desc="request">
|
||||||
#[derive(Debug, Display)]
|
#[derive(Debug, Error)]
|
||||||
pub enum RequestError {
|
pub enum RequestError {
|
||||||
#[display(fmt = "Telegram error #{}: {}", status_code, description)]
|
#[error("A Telegram's error #{status_code}: {description}")]
|
||||||
ApiError {
|
ApiError {
|
||||||
status_code: StatusCode,
|
status_code: StatusCode,
|
||||||
description: String,
|
description: String,
|
||||||
|
@ -31,30 +23,19 @@ pub enum RequestError {
|
||||||
|
|
||||||
/// The group has been migrated to a supergroup with the specified
|
/// The group has been migrated to a supergroup with the specified
|
||||||
/// identifier.
|
/// identifier.
|
||||||
#[display(fmt = "The group has been migrated to a supergroup with id {id}", id = _0)]
|
#[error("The group has been migrated to a supergroup with ID #{0}")]
|
||||||
MigrateToChatId(i64),
|
MigrateToChatId(i64),
|
||||||
|
|
||||||
/// In case of exceeding flood control, the number of seconds left to wait
|
/// In case of exceeding flood control, the number of seconds left to wait
|
||||||
/// before the request can be repeated
|
/// before the request can be repeated
|
||||||
#[display(fmt = "Retry after {secs} seconds", secs = _0)]
|
#[error("Retry after {0} seconds")]
|
||||||
RetryAfter(i32),
|
RetryAfter(i32),
|
||||||
|
|
||||||
#[display(fmt = "Network error: {err}", err = _0)]
|
#[error("A network error: {0}")]
|
||||||
NetworkError(reqwest::Error),
|
NetworkError(#[source] reqwest::Error),
|
||||||
|
|
||||||
#[display(fmt = "InvalidJson error caused by: {err}", err = _0)]
|
#[error("An error while parsing JSON: {0}")]
|
||||||
InvalidJson(serde_json::Error),
|
InvalidJson(#[source] serde_json::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::Error for RequestError {
|
|
||||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
|
||||||
match self {
|
|
||||||
RequestError::ApiError { .. } => None,
|
|
||||||
RequestError::MigrateToChatId(_) => None,
|
|
||||||
RequestError::RetryAfter(_) => None,
|
|
||||||
RequestError::NetworkError(err) => Some(err),
|
|
||||||
RequestError::InvalidJson(err) => Some(err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#![feature(termination_trait_lib)]
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate derive_more;
|
extern crate derive_more;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate thiserror;
|
||||||
|
|
||||||
pub use errors::{DownloadError, RequestError};
|
pub use errors::{DownloadError, RequestError};
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
use bytes::Buf;
|
use reqwest::Client;
|
||||||
use futures::StreamExt;
|
use tokio::io::{AsyncWrite, AsyncWriteExt};
|
||||||
use reqwest::r#async::{Chunk, Client};
|
|
||||||
use tokio::{
|
#[cfg(feature = "unstable-stream")]
|
||||||
io::{AsyncWrite, AsyncWriteExt},
|
use ::{bytes::Bytes, tokio::stream::Stream};
|
||||||
stream::Stream,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::DownloadError;
|
use crate::DownloadError;
|
||||||
|
|
||||||
|
@ -19,25 +17,38 @@ pub async fn download_file<D>(
|
||||||
where
|
where
|
||||||
D: AsyncWrite + Unpin,
|
D: AsyncWrite + Unpin,
|
||||||
{
|
{
|
||||||
let mut stream = download_file_stream(client, token, path).await?;
|
let mut res = client
|
||||||
|
.get(&super::file_url(TELEGRAM_API_URL, token, path))
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.error_for_status()?;
|
||||||
|
|
||||||
while let Some(chunk) = stream.next().await {
|
while let Some(chunk) = res.chunk().await? {
|
||||||
let chunk = chunk?;
|
destination.write_all(&chunk).await?;
|
||||||
destination.write_all(chunk.bytes()).await?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "unstable-stream")]
|
||||||
pub async fn download_file_stream(
|
pub async fn download_file_stream(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
token: &str,
|
token: &str,
|
||||||
path: &str,
|
path: &str,
|
||||||
) -> Result<impl Stream<Item = Result<Chunk, reqwest::Error>>, reqwest::Error> {
|
) -> Result<impl Stream<Item = reqwest::Result<Bytes>>, reqwest::Error> {
|
||||||
Ok(client
|
let res = client
|
||||||
.get(&super::file_url(TELEGRAM_API_URL, token, path))
|
.get(&super::file_url(TELEGRAM_API_URL, token, path))
|
||||||
.send()
|
.send()
|
||||||
.await?
|
.await?
|
||||||
.error_for_status()?
|
.error_for_status()?;
|
||||||
.into_body())
|
|
||||||
|
Ok(futures::stream::unfold(res, |mut res| {
|
||||||
|
async {
|
||||||
|
match res.chunk().await {
|
||||||
|
Err(err) => Some((Err(err), res)),
|
||||||
|
Ok(Some(c)) => Some((Ok(c), res)),
|
||||||
|
Ok(None) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
pub use download::{download_file, download_file_stream};
|
#[cfg(feature = "unstable-stream")]
|
||||||
pub use request::{request_json, request_multipart};
|
pub use download::download_file_stream;
|
||||||
pub use telegram_response::TelegramResponse;
|
|
||||||
|
pub use self::{
|
||||||
|
download::download_file,
|
||||||
|
request::{request_json, request_multipart},
|
||||||
|
telegram_response::TelegramResponse,
|
||||||
|
};
|
||||||
|
|
||||||
mod download;
|
mod download;
|
||||||
mod request;
|
mod request;
|
||||||
|
@ -22,7 +27,7 @@ fn method_url(base: &str, token: &str, method_name: &str) -> String {
|
||||||
|
|
||||||
/// Creates URL for downloading a file. See the [Telegram documentation].
|
/// Creates URL for downloading a file. See the [Telegram documentation].
|
||||||
///
|
///
|
||||||
/// [Telegram documentation] (https://core.telegram.org/bots/api#file)
|
/// [Telegram documentation]: https://core.telegram.org/bots/api#file
|
||||||
fn file_url(base: &str, token: &str, file_path: &str) -> String {
|
fn file_url(base: &str, token: &str, file_path: &str) -> String {
|
||||||
format!(
|
format!(
|
||||||
"{url}/file/bot{token}/{file}",
|
"{url}/file/bot{token}/{file}",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use apply::Apply;
|
use apply::Apply;
|
||||||
use reqwest::r#async::{multipart::Form, Client, Response};
|
use reqwest::{multipart::Form, Client, Response};
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
|
|
||||||
use crate::{requests::ResponseResult, RequestError};
|
use crate::{requests::ResponseResult, RequestError};
|
||||||
|
@ -29,12 +29,16 @@ where
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn request_json<T: DeserializeOwned, P: Serialize>(
|
pub async fn request_json<T, P>(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
token: &str,
|
token: &str,
|
||||||
method_name: &str,
|
method_name: &str,
|
||||||
params: &P,
|
params: &P,
|
||||||
) -> ResponseResult<T> {
|
) -> ResponseResult<T>
|
||||||
|
where
|
||||||
|
T: DeserializeOwned,
|
||||||
|
P: Serialize,
|
||||||
|
{
|
||||||
process_response(
|
process_response(
|
||||||
client
|
client
|
||||||
.post(&super::method_url(TELEGRAM_API_URL, token, method_name))
|
.post(&super::method_url(TELEGRAM_API_URL, token, method_name))
|
||||||
|
@ -46,9 +50,10 @@ pub async fn request_json<T: DeserializeOwned, P: Serialize>(
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn process_response<T: DeserializeOwned>(
|
async fn process_response<T>(response: Response) -> ResponseResult<T>
|
||||||
mut response: Response,
|
where
|
||||||
) -> ResponseResult<T> {
|
T: DeserializeOwned,
|
||||||
|
{
|
||||||
serde_json::from_str::<TelegramResponse<T>>(
|
serde_json::from_str::<TelegramResponse<T>>(
|
||||||
&response.text().await.map_err(RequestError::NetworkError)?,
|
&response.text().await.map_err(RequestError::NetworkError)?,
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,6 +12,8 @@ use crate::{
|
||||||
/// pre_checkout_query. Use this method to respond to such pre-checkout queries.
|
/// pre_checkout_query. Use this method to respond to such pre-checkout queries.
|
||||||
/// On success, True is returned. Note: The Bot API must receive an answer
|
/// On success, True is returned. Note: The Bot API must receive an answer
|
||||||
/// within 10 seconds after the pre-checkout query was sent.
|
/// within 10 seconds after the pre-checkout query was sent.
|
||||||
|
///
|
||||||
|
/// [`Update`]: crate::types::Update
|
||||||
pub struct AnswerPreCheckoutQuery<'a> {
|
pub struct AnswerPreCheckoutQuery<'a> {
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
|
@ -56,40 +58,44 @@ impl AnswerPreCheckoutQuery<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AnswerPreCheckoutQuery<'a> {
|
impl<'a> AnswerPreCheckoutQuery<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<S, B>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
pre_checkout_query_id: String,
|
pre_checkout_query_id: S,
|
||||||
ok: bool,
|
ok: B,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
B: Into<bool>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
pre_checkout_query_id,
|
pre_checkout_query_id: pre_checkout_query_id.into(),
|
||||||
ok,
|
ok: ok.into(),
|
||||||
error_message: None,
|
error_message: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pre_checkout_query_id<T>(mut self, pre_checkout_query_id: T) -> Self
|
pub fn pre_checkout_query_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
self.pre_checkout_query_id = pre_checkout_query_id.into();
|
self.pre_checkout_query_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ok<T>(mut self, ok: T) -> Self
|
pub fn ok<B>(mut self, value: B) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
B: Into<bool>,
|
||||||
{
|
{
|
||||||
self.ok = ok.into();
|
self.ok = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error_message<T>(mut self, error_message: T) -> Self
|
pub fn error_message<S>(mut self, value: S) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
S: Into<String>,
|
||||||
{
|
{
|
||||||
self.error_message = Some(error_message.into());
|
self.error_message = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ use crate::{
|
||||||
/// is_flexible was specified, the Bot API will send an [`Update`] with a
|
/// is_flexible was specified, the Bot API will send an [`Update`] with a
|
||||||
/// shipping_query field to the bot. Use this method to reply to shipping
|
/// shipping_query field to the bot. Use this method to reply to shipping
|
||||||
/// queries. On success, True is returned.
|
/// queries. On success, True is returned.
|
||||||
|
///
|
||||||
|
/// [`Update`]: crate::types::Update
|
||||||
pub struct AnswerShippingQuery<'a> {
|
pub struct AnswerShippingQuery<'a> {
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
|
@ -57,49 +59,53 @@ impl AnswerShippingQuery<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AnswerShippingQuery<'a> {
|
impl<'a> AnswerShippingQuery<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<S, B>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
shipping_query_id: String,
|
shipping_query_id: S,
|
||||||
ok: bool,
|
ok: B,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
B: Into<bool>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
shipping_query_id,
|
shipping_query_id: shipping_query_id.into(),
|
||||||
ok,
|
ok: ok.into(),
|
||||||
shipping_options: None,
|
shipping_options: None,
|
||||||
error_message: None,
|
error_message: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shipping_query_id<T>(mut self, shipping_query_id: T) -> Self
|
pub fn shipping_query_id<S>(mut self, value: S) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
S: Into<String>,
|
||||||
{
|
{
|
||||||
self.shipping_query_id = shipping_query_id.into();
|
self.shipping_query_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ok<T>(mut self, ok: T) -> Self
|
pub fn ok<B>(mut self, value: B) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
B: Into<bool>,
|
||||||
{
|
{
|
||||||
self.ok = ok.into();
|
self.ok = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shipping_options<T>(mut self, shipping_options: T) -> Self
|
pub fn shipping_options<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<Vec<ShippingOption>>,
|
T: Into<Vec<ShippingOption>>,
|
||||||
{
|
{
|
||||||
self.shipping_options = Some(shipping_options.into());
|
self.shipping_options = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error_message<T>(mut self, error_message: T) -> Self
|
pub fn error_message<S>(mut self, value: S) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
S: Into<String>,
|
||||||
{
|
{
|
||||||
self.error_message = Some(error_message.into());
|
self.error_message = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,19 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{ChatId, Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
types::{Message, ReplyMarkup},
|
types::{ChatId, Message, ReplyMarkup},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
/// Use this method to edit live location messages. A location can be edited
|
/// Use this method to edit live location messages. A location can be edited
|
||||||
/// until its live_period expires or editing is explicitly disabled by a
|
/// until its live_period expires or editing is explicitly disabled by a
|
||||||
/// call to [`stopMessageLiveLocation`]. On success, if the edited message
|
/// call to [`StopMessageLiveLocation`]. On success, if the edited message
|
||||||
/// was sent by the bot, the edited [`Message`] is returned, otherwise True
|
/// was sent by the bot, the edited [`Message`] is returned, otherwise True
|
||||||
/// is returned.
|
/// is returned.
|
||||||
|
///
|
||||||
|
/// [`StopMessageLiveLocation`]: crate::requests::StopMessageLiveLocation
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
pub struct EditMessageLiveLocation<'a> {
|
pub struct EditMessageLiveLocation<'a> {
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
|
@ -60,47 +63,63 @@ impl EditMessageLiveLocation<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> EditMessageLiveLocation<'a> {
|
impl<'a> EditMessageLiveLocation<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<Lt, Lg>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
latitude: f64,
|
latitude: Lt,
|
||||||
longitude: f64,
|
longitude: Lg,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
Lt: Into<f64>,
|
||||||
|
Lg: Into<f64>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id: None,
|
chat_id: None,
|
||||||
message_id: None,
|
message_id: None,
|
||||||
inline_message_id: None,
|
inline_message_id: None,
|
||||||
latitude,
|
latitude: latitude.into(),
|
||||||
longitude,
|
longitude: longitude.into(),
|
||||||
reply_markup: None,
|
reply_markup: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T: Into<ChatId>>(mut self, chat_id: T) -> Self {
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
self.chat_id = Some(chat_id.into());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn message_id<T: Into<i32>>(mut self, message_id: T) -> Self {
|
|
||||||
self.message_id = Some(message_id.into());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn inline_message_id<T>(mut self, inline_message_id: T) -> Self
|
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<ChatId>,
|
||||||
{
|
{
|
||||||
self.inline_message_id = Some(inline_message_id.into());
|
self.chat_id = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn latitude<T: Into<f64>>(mut self, latitude: T) -> Self {
|
pub fn message_id<T>(mut self, value: T) -> Self
|
||||||
self.latitude = latitude.into();
|
where
|
||||||
|
T: Into<i32>,
|
||||||
|
{
|
||||||
|
self.message_id = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn longitude<T: Into<f64>>(mut self, longitude: T) -> Self {
|
pub fn inline_message_id<S>(mut self, value: S) -> Self
|
||||||
self.longitude = longitude.into();
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
self.inline_message_id = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn latitude<Lt>(mut self, value: Lt) -> Self
|
||||||
|
where
|
||||||
|
Lt: Into<f64>,
|
||||||
|
{
|
||||||
|
self.latitude = value.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn longitude<Lg>(mut self, value: Lg) -> Self
|
||||||
|
where
|
||||||
|
Lg: Into<f64>,
|
||||||
|
{
|
||||||
|
self.longitude = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use reqwest::r#async::multipart::Form;
|
use reqwest::multipart::Form;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
requests::{utils, ChatId},
|
requests::utils,
|
||||||
types::{InputMedia, ParseMode},
|
types::{ChatId, InputMedia, ParseMode},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This is a convenient struct that builds `reqwest::r#async::multipart::Form`
|
/// This is a convenient struct that builds `reqwest::multipart::Form`
|
||||||
/// from scratch.
|
/// from scratch.
|
||||||
pub struct FormBuilder {
|
pub struct FormBuilder {
|
||||||
form: Form,
|
form: Form,
|
||||||
|
|
|
@ -2,8 +2,8 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{ChatId, Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
types::Message,
|
types::{ChatId, Message},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
@ -50,38 +50,56 @@ impl ForwardMessage<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ForwardMessage<'a> {
|
impl<'a> ForwardMessage<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<C, Fc, M>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
from_chat_id: ChatId,
|
from_chat_id: Fc,
|
||||||
message_id: i32,
|
message_id: M,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
Fc: Into<ChatId>,
|
||||||
|
M: Into<i32>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
from_chat_id,
|
from_chat_id: from_chat_id.into(),
|
||||||
message_id,
|
message_id: message_id.into(),
|
||||||
disable_notification: None,
|
disable_notification: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T: Into<ChatId>>(mut self, val: T) -> Self {
|
pub fn chat_id<C>(mut self, value: C) -> Self
|
||||||
self.chat_id = val.into();
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
{
|
||||||
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_chat_id<T: Into<ChatId>>(mut self, val: T) -> Self {
|
#[allow(clippy::wrong_self_convention)]
|
||||||
self.from_chat_id = val.into();
|
pub fn from_chat_id<C>(mut self, value: C) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
{
|
||||||
|
self.from_chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn message_id<T: Into<i32>>(mut self, val: T) -> Self {
|
pub fn message_id<M>(mut self, value: M) -> Self
|
||||||
self.message_id = val.into();
|
where
|
||||||
|
M: Into<i32>,
|
||||||
|
{
|
||||||
|
self.message_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_notification<T: Into<bool>>(mut self, val: T) -> Self {
|
pub fn disable_notification<B>(mut self, value: B) -> Self
|
||||||
self.disable_notification = Some(val.into());
|
where
|
||||||
|
B: Into<bool>,
|
||||||
|
{
|
||||||
|
self.disable_notification = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{ChatId, Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
types::Chat,
|
types::{Chat, ChatId},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Use this method to get up to date information about the chat
|
/// Use this method to get up to date information about the chat
|
||||||
|
@ -41,11 +41,11 @@ impl GetChat<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> GetChat<'a> {
|
impl<'a> GetChat<'a> {
|
||||||
pub fn chat_id<T>(mut self, chat_id: T) -> Self
|
pub fn chat_id<C>(mut self, value: C) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ChatId>,
|
C: Into<ChatId>,
|
||||||
{
|
{
|
||||||
self.chat_id = chat_id.into();
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,15 +43,21 @@ impl GetFile<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> GetFile<'a> {
|
impl<'a> GetFile<'a> {
|
||||||
pub(crate) fn new(ctx: RequestContext<'a>, file_id: String) -> Self {
|
pub(crate) fn new<F>(ctx: RequestContext<'a>, value: F) -> Self
|
||||||
Self { ctx, file_id }
|
where
|
||||||
|
F: Into<String>,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
ctx,
|
||||||
|
file_id: value.into(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_id<T>(mut self, file_id: T) -> Self
|
pub fn file_id<F>(mut self, value: F) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
F: Into<String>,
|
||||||
{
|
{
|
||||||
self.file_id = file_id.into();
|
self.file_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,35 +61,35 @@ impl<'a> GetUpdates<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset<T>(mut self, offset: T) -> Self
|
pub fn offset<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<i32>,
|
T: Into<i32>,
|
||||||
{
|
{
|
||||||
self.offset = Some(offset.into());
|
self.offset = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn limit<T>(mut self, limit: T) -> Self
|
pub fn limit<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<u8>,
|
T: Into<u8>,
|
||||||
{
|
{
|
||||||
self.limit = Some(limit.into());
|
self.limit = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn timeout<T>(mut self, timeout: T) -> Self
|
pub fn timeout<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<u32>,
|
T: Into<u32>,
|
||||||
{
|
{
|
||||||
self.timeout = Some(timeout.into());
|
self.timeout = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allowed_updates<T>(mut self, allowed_updates: T) -> Self
|
pub fn allowed_updates<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<Vec<AllowedUpdate>>,
|
T: Into<Vec<AllowedUpdate>>,
|
||||||
{
|
{
|
||||||
self.allowed_updates = Some(allowed_updates.into());
|
self.allowed_updates = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,36 +46,39 @@ impl GetUserProfilePhotos<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> GetUserProfilePhotos<'a> {
|
impl<'a> GetUserProfilePhotos<'a> {
|
||||||
pub fn new(ctx: RequestContext<'a>, user_id: i32) -> Self {
|
pub fn new<U>(ctx: RequestContext<'a>, user_id: U) -> Self
|
||||||
|
where
|
||||||
|
U: Into<i32>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
user_id,
|
user_id: user_id.into(),
|
||||||
offset: None,
|
offset: None,
|
||||||
limit: None,
|
limit: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn user_id<T>(mut self, user_id: T) -> Self
|
pub fn user_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<i32>,
|
T: Into<i32>,
|
||||||
{
|
{
|
||||||
self.user_id = user_id.into();
|
self.user_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset<T>(mut self, offset: T) -> Self
|
pub fn offset<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<i64>,
|
T: Into<i64>,
|
||||||
{
|
{
|
||||||
self.offset = Some(offset.into());
|
self.offset = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn limit<T>(mut self, limit: T) -> Self
|
pub fn limit<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<i64>,
|
T: Into<i64>,
|
||||||
{
|
{
|
||||||
self.limit = Some(limit.into());
|
self.limit = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{ChatId, Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
types::True,
|
types::{ChatId, True},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Use this method to kick a user from a group, a supergroup or a channel. In
|
/// Use this method to kick a user from a group, a supergroup or a channel. In
|
||||||
|
@ -28,7 +28,7 @@ pub struct KickChatMember<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<'a> Request for KickChatMember<'a> {
|
impl Request for KickChatMember<'_> {
|
||||||
type ReturnValue = True;
|
type ReturnValue = True;
|
||||||
|
|
||||||
async fn send_boxed(self) -> ResponseResult<Self::ReturnValue> {
|
async fn send_boxed(self) -> ResponseResult<Self::ReturnValue> {
|
||||||
|
@ -49,31 +49,44 @@ impl KickChatMember<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> KickChatMember<'a> {
|
impl<'a> KickChatMember<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<C, U>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
user_id: i32,
|
user_id: U,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
U: Into<i32>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
user_id,
|
user_id: user_id.into(),
|
||||||
until_date: None,
|
until_date: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T: Into<ChatId>>(mut self, chat_id: T) -> Self {
|
pub fn chat_id<C>(mut self, value: C) -> Self
|
||||||
self.chat_id = chat_id.into();
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
{
|
||||||
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn user_id<T: Into<i32>>(mut self, user_id: T) -> Self {
|
pub fn user_id<U>(mut self, value: U) -> Self
|
||||||
self.user_id = user_id.into();
|
where
|
||||||
|
U: Into<i32>,
|
||||||
|
{
|
||||||
|
self.user_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn until_date<T: Into<u64>>(mut self, until_date: T) -> Self {
|
pub fn until_date<T>(mut self, value: T) -> Self
|
||||||
self.until_date = Some(until_date.into());
|
where
|
||||||
|
T: Into<u64>,
|
||||||
|
{
|
||||||
|
self.until_date = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use async_trait::async_trait;
|
use reqwest::Client;
|
||||||
use reqwest::r#async::Client;
|
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::RequestError;
|
use crate::RequestError;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
|
@ -27,61 +28,6 @@ pub use self::{
|
||||||
mod form_builder;
|
mod form_builder;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
pub type ResponseResult<T> = Result<T, RequestError>;
|
|
||||||
|
|
||||||
/// Request that can be sent to telegram.
|
|
||||||
/// `ReturnValue` - a type that will be returned from Telegram.
|
|
||||||
#[async_trait]
|
|
||||||
pub trait Request {
|
|
||||||
type ReturnValue: DeserializeOwned;
|
|
||||||
|
|
||||||
/// Send request to telegram
|
|
||||||
async fn send_boxed(self) -> ResponseResult<Self::ReturnValue>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct RequestContext<'a> {
|
|
||||||
pub client: &'a Client,
|
|
||||||
pub token: &'a str,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Unique identifier for the target chat or username of the target channel (in
|
|
||||||
/// the format @channelusername)
|
|
||||||
#[derive(Debug, Display, Serialize, From, PartialEq, Eq, Clone)]
|
|
||||||
#[serde(untagged)]
|
|
||||||
pub enum ChatId {
|
|
||||||
/// chat identifier
|
|
||||||
#[display(fmt = "{}", _0)]
|
|
||||||
Id(i64),
|
|
||||||
/// _channel_ username (in the format @channelusername)
|
|
||||||
#[display(fmt = "{}", _0)]
|
|
||||||
ChannelUsername(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn chat_id_id_serialization() {
|
|
||||||
let expected_json = String::from(r#"123456"#);
|
|
||||||
let actual_json = serde_json::to_string(&ChatId::Id(123456)).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(expected_json, actual_json)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn chat_id_channel_username_serialization() {
|
|
||||||
let expected_json = String::from(r#""@username""#);
|
|
||||||
let actual_json = serde_json::to_string(&ChatId::ChannelUsername(
|
|
||||||
String::from("@username"),
|
|
||||||
))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(expected_json, actual_json)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod answer_pre_checkout_query;
|
mod answer_pre_checkout_query;
|
||||||
mod answer_shipping_query;
|
mod answer_shipping_query;
|
||||||
mod edit_message_live_location;
|
mod edit_message_live_location;
|
||||||
|
@ -112,3 +58,21 @@ mod send_voice;
|
||||||
mod stop_message_live_location;
|
mod stop_message_live_location;
|
||||||
mod unban_chat_member;
|
mod unban_chat_member;
|
||||||
mod unpin_chat_message;
|
mod unpin_chat_message;
|
||||||
|
|
||||||
|
pub type ResponseResult<T> = Result<T, RequestError>;
|
||||||
|
|
||||||
|
/// A request that can be sent to Telegram.
|
||||||
|
#[async_trait]
|
||||||
|
pub trait Request {
|
||||||
|
/// A type of response.
|
||||||
|
type ReturnValue: DeserializeOwned;
|
||||||
|
|
||||||
|
/// Send this request.
|
||||||
|
async fn send_boxed(self) -> ResponseResult<Self::ReturnValue>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct RequestContext<'a> {
|
||||||
|
pub client: &'a Client,
|
||||||
|
pub token: &'a str,
|
||||||
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{ChatId, Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
types::True,
|
types::{ChatId, True},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Use this method to get up to date information about the chat
|
/// Use this method to get up to date information about the chat
|
||||||
|
@ -22,30 +22,34 @@ pub struct PinChatMessage<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PinChatMessage<'a> {
|
impl<'a> PinChatMessage<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<C, M>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
message_id: i32,
|
message_id: M,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
M: Into<i32>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
message_id,
|
message_id: message_id.into(),
|
||||||
disable_notification: None,
|
disable_notification: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_notification<T>(mut self, val: T) -> Self
|
pub fn disable_notification<B>(mut self, value: B) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
B: Into<bool>,
|
||||||
{
|
{
|
||||||
self.disable_notification = Some(val.into());
|
self.disable_notification = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<'a> Request for PinChatMessage<'a> {
|
impl Request for PinChatMessage<'_> {
|
||||||
type ReturnValue = True;
|
type ReturnValue = True;
|
||||||
async fn send_boxed(self) -> ResponseResult<Self::ReturnValue> {
|
async fn send_boxed(self) -> ResponseResult<Self::ReturnValue> {
|
||||||
self.send().await
|
self.send().await
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use crate::network;
|
|
||||||
use crate::requests::{ChatId, Request, RequestContext, ResponseResult};
|
|
||||||
use crate::types::True;
|
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
network,
|
||||||
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
|
types::{ChatId, True},
|
||||||
|
};
|
||||||
|
|
||||||
///Use this method to promote or demote a user in a supergroup or a channel.
|
///Use this method to promote or demote a user in a supergroup or a channel.
|
||||||
/// The bot must be an administrator in the chat for this to work and must have
|
/// The bot must be an administrator in the chat for this to work and must have
|
||||||
/// the appropriate admin rights. Pass False for all boolean parameters to
|
/// the appropriate admin rights. Pass False for all boolean parameters to
|
||||||
|
@ -47,6 +49,7 @@ pub struct PromoteChatMember<'a> {
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub can_promote_members: Option<bool>,
|
pub can_promote_members: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Request for PromoteChatMember<'_> {
|
impl Request for PromoteChatMember<'_> {
|
||||||
type ReturnValue = True;
|
type ReturnValue = True;
|
||||||
|
@ -67,16 +70,21 @@ impl PromoteChatMember<'_> {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PromoteChatMember<'a> {
|
impl<'a> PromoteChatMember<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<C, U>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
user_id: i32,
|
user_id: U,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
U: Into<i32>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
user_id,
|
user_id: user_id.into(),
|
||||||
can_change_info: None,
|
can_change_info: None,
|
||||||
can_post_messages: None,
|
can_post_messages: None,
|
||||||
can_edit_messages: None,
|
can_edit_messages: None,
|
||||||
|
@ -88,83 +96,83 @@ impl<'a> PromoteChatMember<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T>(mut self, chat_id: T) -> Self
|
pub fn chat_id<C>(mut self, value: C) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ChatId>,
|
C: Into<ChatId>,
|
||||||
{
|
{
|
||||||
self.chat_id = chat_id.into();
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn user_id<T>(mut self, user_id: T) -> Self
|
pub fn user_id<U>(mut self, value: U) -> Self
|
||||||
where
|
where
|
||||||
T: Into<i32>,
|
U: Into<i32>,
|
||||||
{
|
{
|
||||||
self.user_id = user_id.into();
|
self.user_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_change_info<T>(mut self, can_change_info: T) -> Self
|
pub fn can_change_info<B>(mut self, value: B) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
B: Into<bool>,
|
||||||
{
|
{
|
||||||
self.can_change_info = Some(can_change_info.into());
|
self.can_change_info = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_post_messages<T>(mut self, can_post_messages: T) -> Self
|
pub fn can_post_messages<B>(mut self, value: B) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
B: Into<bool>,
|
||||||
{
|
{
|
||||||
self.can_post_messages = Some(can_post_messages.into());
|
self.can_post_messages = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_edit_messages<T>(mut self, can_edit_messages: T) -> Self
|
pub fn can_edit_messages<B>(mut self, value: B) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
B: Into<bool>,
|
||||||
{
|
{
|
||||||
self.can_edit_messages = Some(can_edit_messages.into());
|
self.can_edit_messages = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_delete_messages<T>(mut self, can_delete_messages: T) -> Self
|
pub fn can_delete_messages<B>(mut self, value: B) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
B: Into<bool>,
|
||||||
{
|
{
|
||||||
self.can_delete_messages = Some(can_delete_messages.into());
|
self.can_delete_messages = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_invite_users<T>(mut self, can_invite_users: T) -> Self
|
pub fn can_invite_users<B>(mut self, value: B) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
B: Into<bool>,
|
||||||
{
|
{
|
||||||
self.can_invite_users = Some(can_invite_users.into());
|
self.can_invite_users = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_restrict_members<T>(mut self, can_restrict_members: T) -> Self
|
pub fn can_restrict_members<B>(mut self, value: B) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
B: Into<bool>,
|
||||||
{
|
{
|
||||||
self.can_restrict_members = Some(can_restrict_members.into());
|
self.can_restrict_members = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_pin_messages<T>(mut self, can_pin_messages: T) -> Self
|
pub fn can_pin_messages<B>(mut self, value: B) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
B: Into<bool>,
|
||||||
{
|
{
|
||||||
self.can_pin_messages = Some(can_pin_messages.into());
|
self.can_pin_messages = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_promote_members<T>(mut self, can_promote_members: T) -> Self
|
pub fn can_promote_members<B>(mut self, value: B) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
B: Into<bool>,
|
||||||
{
|
{
|
||||||
self.can_promote_members = Some(can_promote_members.into());
|
self.can_promote_members = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{ChatId, Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
types::{ChatPermissions, True},
|
types::{ChatId, ChatPermissions, True},
|
||||||
};
|
};
|
||||||
use async_trait::async_trait;
|
|
||||||
|
|
||||||
/// Use this method to restrict a user in a supergroup. The bot must be an
|
/// Use this method to restrict a user in a supergroup. The bot must be an
|
||||||
/// administrator in the supergroup for this to work and must have the
|
/// administrator in the supergroup for this to work and must have the
|
||||||
|
@ -28,7 +29,7 @@ pub struct RestrictChatMember<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<'a> Request for RestrictChatMember<'a> {
|
impl Request for RestrictChatMember<'_> {
|
||||||
type ReturnValue = True;
|
type ReturnValue = True;
|
||||||
|
|
||||||
async fn send_boxed(self) -> ResponseResult<Self::ReturnValue> {
|
async fn send_boxed(self) -> ResponseResult<Self::ReturnValue> {
|
||||||
|
@ -49,50 +50,55 @@ impl RestrictChatMember<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> RestrictChatMember<'a> {
|
impl<'a> RestrictChatMember<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<C, U, P>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
user_id: i32,
|
user_id: U,
|
||||||
permissions: ChatPermissions,
|
permissions: P,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
U: Into<i32>,
|
||||||
|
P: Into<ChatPermissions>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
user_id,
|
user_id: user_id.into(),
|
||||||
permissions,
|
permissions: permissions.into(),
|
||||||
until_date: None,
|
until_date: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T>(mut self, chat_id: T) -> Self
|
pub fn chat_id<C>(mut self, value: C) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ChatId>,
|
C: Into<ChatId>,
|
||||||
{
|
{
|
||||||
self.chat_id = chat_id.into();
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn user_id<T>(mut self, user_id: T) -> Self
|
pub fn user_id<U>(mut self, value: U) -> Self
|
||||||
where
|
where
|
||||||
T: Into<i32>,
|
U: Into<i32>,
|
||||||
{
|
{
|
||||||
self.user_id = user_id.into();
|
self.user_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn permissions<T>(mut self, permissions: T) -> Self
|
pub fn permissions<P>(mut self, value: P) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ChatPermissions>,
|
P: Into<ChatPermissions>,
|
||||||
{
|
{
|
||||||
self.permissions = permissions.into();
|
self.permissions = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn until_date<T>(mut self, until_date: T) -> Self
|
pub fn until_date<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<u64>,
|
T: Into<u64>,
|
||||||
{
|
{
|
||||||
self.until_date = Some(until_date.into());
|
self.until_date = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,186 @@
|
||||||
use crate::requests::RequestContext;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
///TODO: add implementation
|
use crate::network;
|
||||||
|
use crate::requests::{Request, RequestContext, ResponseResult};
|
||||||
|
use crate::types::{ChatId, Message, ParseMode, ReplyMarkup};
|
||||||
|
|
||||||
|
///TODO: add to bot api
|
||||||
|
///Use this method to send animation files (GIF or H.264/MPEG-4 AVC video
|
||||||
|
/// without sound). On success, the sent Message is returned. Bots can currently
|
||||||
|
/// send animation files of up to 50 MB in size, this limit may be changed in
|
||||||
|
/// the future.
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub struct SendAnimation<'a> {
|
pub struct SendAnimation<'a> {
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
|
///Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format @channelusername)
|
||||||
|
pub chat_id: ChatId,
|
||||||
|
///Animation to send. Pass a file_id as String to send an animation that
|
||||||
|
/// exists on the Telegram servers (recommended), pass an HTTP URL as a
|
||||||
|
/// String for Telegram to get an animation from the Internet, or upload a
|
||||||
|
/// new animation using multipart/form-data. More info on Sending Files »
|
||||||
|
pub animation: String,
|
||||||
|
// InputFile or String
|
||||||
|
///Duration of sent animation in seconds
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub duration: Option<u64>,
|
||||||
|
///Animation width
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub width: Option<i32>,
|
||||||
|
///Animation height
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub height: Option<i32>,
|
||||||
|
///Thumbnail of the file sent; can be ignored if thumbnail generation for
|
||||||
|
/// the file is supported server-side. The thumbnail should be in JPEG
|
||||||
|
/// format and less than 200 kB in size. A thumbnail‘s width and height
|
||||||
|
/// should not exceed 320. Ignored if the file is not uploaded using
|
||||||
|
/// multipart/form-data. Thumbnails can’t be reused and can be only
|
||||||
|
/// uploaded as a new file, so you can pass “attach://<file_attach_name>”
|
||||||
|
/// if the thumbnail was uploaded using multipart/form-data under
|
||||||
|
/// <file_attach_name> »
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub thumb: Option<String>,
|
||||||
|
// InputFile or String Optional
|
||||||
|
///Animation caption (may also be used when resending animation by
|
||||||
|
/// file_id), 0-1024 characters
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub 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.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub parse_mode: Option<ParseMode>,
|
||||||
|
///Sends the message silently. Users will receive a notification with no
|
||||||
|
/// sound.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub disable_notification: Option<bool>,
|
||||||
|
///If the message is a reply, ID of the original message
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub reply_to_message_id: Option<i32>,
|
||||||
|
///Additional interface options. A JSON-serialized object for an inline
|
||||||
|
/// keyboard, custom reply keyboard, instructions to remove reply keyboard
|
||||||
|
/// or to force a reply from the user.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub reply_markup: Option<ReplyMarkup>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Request for SendAnimation<'_> {
|
||||||
|
type ReturnValue = Message;
|
||||||
|
|
||||||
|
async fn send_boxed(self) -> ResponseResult<Self::ReturnValue> {
|
||||||
|
self.send().await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SendAnimation<'_> {
|
||||||
|
async fn send(self) -> ResponseResult<Message> {
|
||||||
|
network::request_json(
|
||||||
|
&self.ctx.client,
|
||||||
|
&self.ctx.token,
|
||||||
|
"sendAnimation",
|
||||||
|
&self,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> SendAnimation<'a> {
|
||||||
|
pub(crate) fn new<C, S>(
|
||||||
|
ctx: RequestContext<'a>,
|
||||||
|
chat_id: C,
|
||||||
|
animation: S,
|
||||||
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
ctx,
|
||||||
|
chat_id: chat_id.into(),
|
||||||
|
animation: animation.into(),
|
||||||
|
duration: None,
|
||||||
|
width: None,
|
||||||
|
height: None,
|
||||||
|
thumb: None,
|
||||||
|
caption: None,
|
||||||
|
parse_mode: None,
|
||||||
|
disable_notification: None,
|
||||||
|
reply_to_message_id: None,
|
||||||
|
reply_markup: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<ChatId>,
|
||||||
|
{
|
||||||
|
self.chat_id = value.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn duration<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<u64>,
|
||||||
|
{
|
||||||
|
self.duration = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn width<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<i32>,
|
||||||
|
{
|
||||||
|
self.width = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn height<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<i32>,
|
||||||
|
{
|
||||||
|
self.height = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn thumb<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
{
|
||||||
|
self.thumb = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn caption<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
{
|
||||||
|
self.caption = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn parse_mode<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<ParseMode>,
|
||||||
|
{
|
||||||
|
self.parse_mode = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn disable_notification<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<bool>,
|
||||||
|
{
|
||||||
|
self.disable_notification = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn reply_to_message_id<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<i32>,
|
||||||
|
{
|
||||||
|
self.reply_to_message_id = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn reply_markup<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<ReplyMarkup>,
|
||||||
|
{
|
||||||
|
self.reply_markup = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,9 @@ use async_trait::async_trait;
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{
|
requests::{
|
||||||
form_builder::FormBuilder, ChatId, Request, RequestContext,
|
form_builder::FormBuilder, Request, RequestContext, ResponseResult,
|
||||||
ResponseResult,
|
|
||||||
},
|
},
|
||||||
types::{InputFile, Message, ParseMode, ReplyMarkup},
|
types::{ChatId, InputFile, Message, ParseMode, ReplyMarkup},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Use this method to send audio files, if you want Telegram clients to display
|
/// Use this method to send audio files, if you want Telegram clients to display
|
||||||
|
@ -15,6 +14,9 @@ use crate::{
|
||||||
/// to 50 MB in size, this limit may be changed in the future.
|
/// to 50 MB in size, this limit may be changed in the future.
|
||||||
///
|
///
|
||||||
/// For sending voice messages, use the [`SendVoice`] method instead.
|
/// For sending voice messages, use the [`SendVoice`] method instead.
|
||||||
|
///
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
|
/// [`SendVoice`]: crate::requests::SendVoice
|
||||||
pub struct SendAudio<'a> {
|
pub struct SendAudio<'a> {
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
|
|
||||||
|
@ -35,7 +37,7 @@ pub struct SendAudio<'a> {
|
||||||
/// or inline URLs] in the media caption.
|
/// or inline URLs] in the media caption.
|
||||||
///
|
///
|
||||||
/// [Markdown]: crate::types::ParseMode::Markdown
|
/// [Markdown]: crate::types::ParseMode::Markdown
|
||||||
/// [Html]: crate::types::ParseMode::Html
|
/// [HTML]: crate::types::ParseMode::HTML
|
||||||
/// [bold, italic, fixed-width text or inline URLs]:
|
/// [bold, italic, fixed-width text or inline URLs]:
|
||||||
/// crate::types::ParseMode
|
/// crate::types::ParseMode
|
||||||
pub parse_mode: Option<ParseMode>,
|
pub parse_mode: Option<ParseMode>,
|
||||||
|
@ -87,11 +89,13 @@ impl SendAudio<'_> {
|
||||||
"reply_to_message_id",
|
"reply_to_message_id",
|
||||||
self.reply_to_message_id.as_ref(),
|
self.reply_to_message_id.as_ref(),
|
||||||
);
|
);
|
||||||
|
|
||||||
params = match self.audio {
|
params = match self.audio {
|
||||||
InputFile::File(file) => params.add_file("audio", &file),
|
InputFile::File(file) => params.add_file("audio", &file),
|
||||||
InputFile::Url(url) => params.add("audio", &url),
|
InputFile::Url(url) => params.add("audio", &url),
|
||||||
InputFile::FileId(file_id) => params.add("audio", &file_id),
|
InputFile::FileId(file_id) => params.add("audio", &file_id),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(thumb) = self.thumb {
|
if let Some(thumb) = self.thumb {
|
||||||
params = match thumb {
|
params = match thumb {
|
||||||
InputFile::File(file) => params.add_file("thumb", &file),
|
InputFile::File(file) => params.add_file("thumb", &file),
|
||||||
|
@ -99,28 +103,31 @@ impl SendAudio<'_> {
|
||||||
InputFile::FileId(file_id) => params.add("thumb", &file_id),
|
InputFile::FileId(file_id) => params.add("thumb", &file_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let params = params.build();
|
|
||||||
|
|
||||||
network::request_multipart(
|
network::request_multipart(
|
||||||
&self.ctx.client,
|
&self.ctx.client,
|
||||||
&self.ctx.token,
|
&self.ctx.token,
|
||||||
"sendAudio",
|
"sendAudio",
|
||||||
Some(params),
|
Some(params.build()),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SendAudio<'a> {
|
impl<'a> SendAudio<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<C, A>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
audio: InputFile,
|
audio: A,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
A: Into<InputFile>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
audio,
|
audio: audio.into(),
|
||||||
caption: None,
|
caption: None,
|
||||||
parse_mode: None,
|
parse_mode: None,
|
||||||
duration: None,
|
duration: None,
|
||||||
|
@ -133,59 +140,83 @@ impl<'a> SendAudio<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T: Into<ChatId>>(mut self, chat_id: T) -> Self {
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
self.chat_id = chat_id.into();
|
where
|
||||||
|
T: Into<ChatId>,
|
||||||
|
{
|
||||||
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn audio<T: Into<InputFile>>(mut self, audio: T) -> Self {
|
pub fn audio<T>(mut self, value: T) -> Self
|
||||||
self.audio = audio.into();
|
where
|
||||||
|
T: Into<InputFile>,
|
||||||
|
{
|
||||||
|
self.audio = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn caption<T: Into<String>>(mut self, caption: T) -> Self {
|
pub fn caption<T>(mut self, value: T) -> Self
|
||||||
self.caption = Some(caption.into());
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
{
|
||||||
|
self.caption = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_mode<T: Into<ParseMode>>(mut self, parse_mode: T) -> Self {
|
pub fn parse_mode<T>(mut self, value: T) -> Self
|
||||||
self.parse_mode = Some(parse_mode.into());
|
where
|
||||||
|
T: Into<ParseMode>,
|
||||||
|
{
|
||||||
|
self.parse_mode = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn duration<T: Into<i32>>(mut self, duration: T) -> Self {
|
pub fn duration<T>(mut self, value: T) -> Self
|
||||||
self.duration = Some(duration.into());
|
where
|
||||||
|
T: Into<i32>,
|
||||||
|
{
|
||||||
|
self.duration = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn performer<T: Into<String>>(mut self, performer: T) -> Self {
|
pub fn performer<T>(mut self, value: T) -> Self
|
||||||
self.performer = Some(performer.into());
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
{
|
||||||
|
self.performer = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn title<T: Into<String>>(mut self, title: T) -> Self {
|
pub fn title<T>(mut self, value: T) -> Self
|
||||||
self.title = Some(title.into());
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
{
|
||||||
|
self.title = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thumb<T: Into<InputFile>>(mut self, thumb: T) -> Self {
|
pub fn thumb<T>(mut self, value: T) -> Self
|
||||||
self.thumb = Some(thumb.into());
|
where
|
||||||
|
T: Into<InputFile>,
|
||||||
|
{
|
||||||
|
self.thumb = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_notification<T: Into<bool>>(
|
pub fn disable_notification<T>(mut self, value: T) -> Self
|
||||||
mut self,
|
where
|
||||||
disable_notification: T,
|
T: Into<bool>,
|
||||||
) -> Self {
|
{
|
||||||
self.disable_notification = Some(disable_notification.into());
|
self.disable_notification = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply_to_message_id<T: Into<i32>>(
|
pub fn reply_to_message_id<T>(mut self, value: T) -> Self
|
||||||
mut self,
|
where
|
||||||
reply_to_message_id: T,
|
T: Into<i32>,
|
||||||
) -> Self {
|
{
|
||||||
self.reply_to_message_id = Some(reply_to_message_id.into());
|
self.reply_to_message_id = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{ChatId, Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
types::True,
|
types::{ChatAction, ChatId, True},
|
||||||
};
|
};
|
||||||
|
|
||||||
///Use this method when you need to tell the user that something is happening
|
///Use this method when you need to tell the user that something is happening
|
||||||
|
@ -25,21 +25,6 @@ pub struct SendChatAction<'a> {
|
||||||
pub action: ChatAction,
|
pub action: ChatAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, From, Clone)]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
pub enum ChatAction {
|
|
||||||
Typing,
|
|
||||||
UploadPhoto,
|
|
||||||
RecordVideo,
|
|
||||||
UploadVideo,
|
|
||||||
RecordAudio,
|
|
||||||
UploadAudio,
|
|
||||||
UploadDocument,
|
|
||||||
FindLocation,
|
|
||||||
RecordVideoNote,
|
|
||||||
UploadVideoNote,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Request for SendChatAction<'_> {
|
impl Request for SendChatAction<'_> {
|
||||||
type ReturnValue = True;
|
type ReturnValue = True;
|
||||||
|
@ -62,31 +47,35 @@ impl SendChatAction<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SendChatAction<'a> {
|
impl<'a> SendChatAction<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<Cid, Ca>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: Cid,
|
||||||
action: ChatAction,
|
action: Ca,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
Cid: Into<ChatId>,
|
||||||
|
Ca: Into<ChatAction>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
action,
|
action: action.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T>(mut self, chat_id: T) -> Self
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ChatId>,
|
T: Into<ChatId>,
|
||||||
{
|
{
|
||||||
self.chat_id = chat_id.into();
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn action<T>(mut self, action: T) -> Self
|
pub fn action<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ChatAction>,
|
T: Into<ChatAction>,
|
||||||
{
|
{
|
||||||
self.action = action.into();
|
self.action = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{ChatId, Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
types::{Message, ReplyMarkup},
|
types::{ChatId, Message, ReplyMarkup},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Use this method to send phone contacts.
|
/// Use this method to send phone contacts.
|
||||||
|
@ -64,17 +64,22 @@ impl SendContact<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SendContact<'a> {
|
impl<'a> SendContact<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<C, P, F>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
phone_number: String,
|
phone_number: P,
|
||||||
first_name: String,
|
first_name: F,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
P: Into<String>,
|
||||||
|
F: Into<String>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
phone_number,
|
phone_number: phone_number.into(),
|
||||||
first_name,
|
first_name: first_name.into(),
|
||||||
last_name: None,
|
last_name: None,
|
||||||
vcard: None,
|
vcard: None,
|
||||||
disable_notification: None,
|
disable_notification: None,
|
||||||
|
@ -83,67 +88,67 @@ impl<'a> SendContact<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T>(mut self, chat_id: T) -> Self
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ChatId>,
|
T: Into<ChatId>,
|
||||||
{
|
{
|
||||||
self.chat_id = chat_id.into();
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn phone_number<T>(mut self, phone_number: T) -> Self
|
pub fn phone_number<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
self.phone_number = phone_number.into();
|
self.phone_number = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn first_name<T>(mut self, first_name: T) -> Self
|
pub fn first_name<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
self.first_name = first_name.into();
|
self.first_name = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn last_name<T>(mut self, last_name: T) -> Self
|
pub fn last_name<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
self.last_name = Some(last_name.into());
|
self.last_name = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vcard<T>(mut self, vcard: T) -> Self
|
pub fn vcard<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
self.vcard = Some(vcard.into());
|
self.vcard = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_notification<T>(mut self, disable_notification: T) -> Self
|
pub fn disable_notification<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
T: Into<bool>,
|
||||||
{
|
{
|
||||||
self.disable_notification = Some(disable_notification.into());
|
self.disable_notification = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply_to_message_id<T>(mut self, reply_to_message_id: T) -> Self
|
pub fn reply_to_message_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<i32>,
|
T: Into<i32>,
|
||||||
{
|
{
|
||||||
self.reply_to_message_id = Some(reply_to_message_id.into());
|
self.reply_to_message_id = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply_markup<T>(mut self, reply_markup: T) -> Self
|
pub fn reply_markup<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ReplyMarkup>,
|
T: Into<ReplyMarkup>,
|
||||||
{
|
{
|
||||||
self.reply_markup = Some(reply_markup.into());
|
self.reply_markup = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,167 @@
|
||||||
use crate::requests::RequestContext;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
///TODO: add implementation
|
use crate::{
|
||||||
|
network,
|
||||||
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
|
types::{ChatId, Message, ParseMode, ReplyMarkup},
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: add method to bot/api
|
||||||
|
|
||||||
|
///Use this method to send general files. On success, the sent Message is
|
||||||
|
/// returned. Bots can currently send files of any type of up to 50 MB in size,
|
||||||
|
/// this limit may be changed in the future.
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub struct SendDocument<'a> {
|
pub struct SendDocument<'a> {
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
|
/// Unique identifier for the target chat or username of the target
|
||||||
|
/// channel (in the format @channelusername)
|
||||||
|
pub chat_id: ChatId,
|
||||||
|
/// File to send. Pass a file_id as String to send a file that exists on
|
||||||
|
/// the Telegram servers (recommended), pass an HTTP URL as a String for
|
||||||
|
/// Telegram to get a file from the Internet, or upload a new one using
|
||||||
|
/// multipart/form-data.»
|
||||||
|
pub document: String,
|
||||||
|
//InputFile or String
|
||||||
|
/// Thumbnail of the file sent; can be ignored if thumbnail generation for
|
||||||
|
/// the file is supported server-side. The thumbnail should be in JPEG
|
||||||
|
/// format and less than 200 kB in size. A thumbnail‘s width and height
|
||||||
|
/// should not exceed 320. Ignored if the file is not uploaded using
|
||||||
|
/// multipart/form-data. Thumbnails can’t be reused and can be only
|
||||||
|
/// uploaded as a new file, so you can pass “attach://<file_attach_name>”
|
||||||
|
/// if the thumbnail was uploaded using multipart/form-data under
|
||||||
|
/// <file_attach_name>. More info on Sending Files »
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub thumb: Option<String>,
|
||||||
|
//InputFile or String
|
||||||
|
/// Document caption (may also be used when resending documents by
|
||||||
|
/// file_id), 0-1024 characters
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub 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.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub parse_mode: Option<ParseMode>,
|
||||||
|
/// Sends the message silently. Users will receive a notification with
|
||||||
|
/// no sound.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub disable_notification: Option<bool>,
|
||||||
|
/// If the message is a reply, ID of the original message
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub reply_to_message_id: Option<i32>,
|
||||||
|
/// Additional interface options. A JSON-serialized
|
||||||
|
/// object for an inline keyboard, custom reply keyboard, instructions to
|
||||||
|
/// remove reply keyboard or to force a reply from the user.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub reply_markup: Option<ReplyMarkup>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Request for SendDocument<'_> {
|
||||||
|
type ReturnValue = Message;
|
||||||
|
|
||||||
|
async fn send_boxed(self) -> ResponseResult<Self::ReturnValue> {
|
||||||
|
self.send().await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SendDocument<'_> {
|
||||||
|
pub async fn send(self) -> ResponseResult<Message> {
|
||||||
|
network::request_json(
|
||||||
|
&self.ctx.client,
|
||||||
|
&self.ctx.token,
|
||||||
|
"sendDocument",
|
||||||
|
&self,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> SendDocument<'a> {
|
||||||
|
pub(crate) fn new<C, D>(
|
||||||
|
ctx: RequestContext<'a>,
|
||||||
|
chat_id: C,
|
||||||
|
document: D,
|
||||||
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
D: Into<String>,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
ctx,
|
||||||
|
chat_id: chat_id.into(),
|
||||||
|
document: document.into(),
|
||||||
|
thumb: None,
|
||||||
|
caption: None,
|
||||||
|
parse_mode: None,
|
||||||
|
disable_notification: None,
|
||||||
|
reply_to_message_id: None,
|
||||||
|
reply_markup: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<ChatId>,
|
||||||
|
{
|
||||||
|
self.chat_id = value.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn document<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
{
|
||||||
|
self.document = value.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn thumb<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
{
|
||||||
|
self.thumb = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn caption<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
{
|
||||||
|
self.caption = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_mode<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<ParseMode>,
|
||||||
|
{
|
||||||
|
self.parse_mode = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disable_notification<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<bool>,
|
||||||
|
{
|
||||||
|
self.disable_notification = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reply_to_message_id<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<i32>,
|
||||||
|
{
|
||||||
|
self.reply_to_message_id = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reply_markup<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<ReplyMarkup>,
|
||||||
|
{
|
||||||
|
self.reply_markup = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use async_trait::async_trait;
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{ChatId, Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
types::{Message, ReplyMarkup},
|
types::{ChatId, Message, ReplyMarkup},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
@ -59,17 +60,22 @@ impl SendLocation<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SendLocation<'a> {
|
impl<'a> SendLocation<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<Lt, Lg, C>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
latitude: f64,
|
latitude: Lt,
|
||||||
longitude: f64,
|
longitude: Lg,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
Lt: Into<f64>,
|
||||||
|
Lg: Into<f64>,
|
||||||
|
C: Into<ChatId>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
latitude,
|
latitude: latitude.into(),
|
||||||
longitude,
|
longitude: longitude.into(),
|
||||||
live_period: None,
|
live_period: None,
|
||||||
disable_notification: None,
|
disable_notification: None,
|
||||||
reply_to_message_id: None,
|
reply_to_message_id: None,
|
||||||
|
@ -77,33 +83,51 @@ impl<'a> SendLocation<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T: Into<ChatId>>(mut self, chat_id: T) -> Self {
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
self.chat_id = chat_id.into();
|
where
|
||||||
|
T: Into<ChatId>,
|
||||||
|
{
|
||||||
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn latitude<T: Into<f64>>(mut self, latitude: T) -> Self {
|
pub fn latitude<Lt>(mut self, value: Lt) -> Self
|
||||||
self.latitude = latitude.into();
|
where
|
||||||
|
Lt: Into<f64>,
|
||||||
|
{
|
||||||
|
self.latitude = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn longitude<T: Into<f64>>(mut self, longitude: T) -> Self {
|
pub fn longitude<Lg>(mut self, value: Lg) -> Self
|
||||||
self.longitude = longitude.into();
|
where
|
||||||
|
Lg: Into<f64>,
|
||||||
|
{
|
||||||
|
self.longitude = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn live_period<T: Into<i32>>(mut self, live_period: T) -> Self {
|
pub fn live_period<T>(mut self, value: T) -> Self
|
||||||
self.live_period = Some(live_period.into());
|
where
|
||||||
|
T: Into<i32>,
|
||||||
|
{
|
||||||
|
self.live_period = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_notification<T: Into<bool>>(mut self, val: T) -> Self {
|
pub fn disable_notification<T>(mut self, value: T) -> Self
|
||||||
self.disable_notification = Some(val.into());
|
where
|
||||||
|
T: Into<bool>,
|
||||||
|
{
|
||||||
|
self.disable_notification = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply_to_message_id<T: Into<i32>>(mut self, val: T) -> Self {
|
pub fn reply_to_message_id<T>(mut self, value: T) -> Self
|
||||||
self.reply_to_message_id = Some(val.into());
|
where
|
||||||
|
T: Into<i32>,
|
||||||
|
{
|
||||||
|
self.reply_to_message_id = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use apply::Apply;
|
use apply::Apply;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network::request_multipart,
|
network::request_multipart,
|
||||||
requests::{
|
requests::{
|
||||||
form_builder::FormBuilder, ChatId, Request, RequestContext,
|
form_builder::FormBuilder, Request, RequestContext, ResponseResult,
|
||||||
ResponseResult,
|
|
||||||
},
|
},
|
||||||
types::{InputFile, InputMedia, Message},
|
types::{ChatId, InputFile, InputMedia, Message},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Use this method to send a group of photos or videos as an album.
|
/// Use this method to send a group of photos or videos as an album.
|
||||||
|
@ -71,37 +71,53 @@ impl SendMediaGroup<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SendMediaGroup<'a> {
|
impl<'a> SendMediaGroup<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<C, M>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
media: Vec<InputMedia>,
|
media: M,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
M: Into<Vec<InputMedia>>,
|
||||||
|
{
|
||||||
SendMediaGroup {
|
SendMediaGroup {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
media,
|
media: media.into(),
|
||||||
disable_notification: None,
|
disable_notification: None,
|
||||||
reply_to_message_id: None,
|
reply_to_message_id: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T: Into<ChatId>>(mut self, val: T) -> Self {
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
self.chat_id = val.into();
|
where
|
||||||
|
T: Into<ChatId>,
|
||||||
|
{
|
||||||
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn media<T: Into<Vec<InputMedia>>>(mut self, val: T) -> Self {
|
pub fn media<T>(mut self, value: T) -> Self
|
||||||
self.media = val.into();
|
where
|
||||||
|
T: Into<Vec<InputMedia>>,
|
||||||
|
{
|
||||||
|
self.media = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_notification<T: Into<bool>>(mut self, val: T) -> Self {
|
pub fn disable_notification<T>(mut self, value: T) -> Self
|
||||||
self.disable_notification = Some(val.into());
|
where
|
||||||
|
T: Into<bool>,
|
||||||
|
{
|
||||||
|
self.disable_notification = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply_to_message_id<T: Into<i32>>(mut self, val: T) -> Self {
|
pub fn reply_to_message_id<T>(mut self, value: T) -> Self
|
||||||
self.reply_to_message_id = Some(val.into());
|
where
|
||||||
|
T: Into<i32>,
|
||||||
|
{
|
||||||
|
self.reply_to_message_id = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{ChatId, Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
types::{Message, ParseMode, ReplyMarkup},
|
types::{ChatId, Message, ParseMode, ReplyMarkup},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
@ -24,7 +24,7 @@ pub struct SendMessage<'a> {
|
||||||
/// or inline URLs] in the media caption.
|
/// or inline URLs] in the media caption.
|
||||||
///
|
///
|
||||||
/// [Markdown]: crate::types::ParseMode::Markdown
|
/// [Markdown]: crate::types::ParseMode::Markdown
|
||||||
/// [Html]: crate::types::ParseMode::Html
|
/// [HTML]: crate::types::ParseMode::HTML
|
||||||
/// [bold, italic, fixed-width text or inline URLs]:
|
/// [bold, italic, fixed-width text or inline URLs]:
|
||||||
/// crate::types::ParseMode
|
/// crate::types::ParseMode
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
@ -65,15 +65,19 @@ impl SendMessage<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SendMessage<'a> {
|
impl<'a> SendMessage<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<C, S>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
text: String,
|
text: S,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
SendMessage {
|
SendMessage {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
text,
|
text: text.into(),
|
||||||
parse_mode: None,
|
parse_mode: None,
|
||||||
disable_web_page_preview: None,
|
disable_web_page_preview: None,
|
||||||
disable_notification: None,
|
disable_notification: None,
|
||||||
|
@ -82,38 +86,59 @@ impl<'a> SendMessage<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T: Into<ChatId>>(mut self, val: T) -> Self {
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
self.chat_id = val.into();
|
where
|
||||||
|
T: Into<ChatId>,
|
||||||
|
{
|
||||||
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn text<T: Into<String>>(mut self, val: T) -> Self {
|
pub fn text<T>(mut self, value: T) -> Self
|
||||||
self.text = val.into();
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
{
|
||||||
|
self.text = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_mode<T: Into<ParseMode>>(mut self, val: T) -> Self {
|
pub fn parse_mode<T>(mut self, value: T) -> Self
|
||||||
self.parse_mode = Some(val.into());
|
where
|
||||||
|
T: Into<ParseMode>,
|
||||||
|
{
|
||||||
|
self.parse_mode = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_web_page_preview<T: Into<bool>>(mut self, val: T) -> Self {
|
pub fn disable_web_page_preview<T>(mut self, value: T) -> Self
|
||||||
self.disable_web_page_preview = Some(val.into());
|
where
|
||||||
|
T: Into<bool>,
|
||||||
|
{
|
||||||
|
self.disable_web_page_preview = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_notification<T: Into<bool>>(mut self, val: T) -> Self {
|
pub fn disable_notification<T>(mut self, value: T) -> Self
|
||||||
self.disable_notification = Some(val.into());
|
where
|
||||||
|
T: Into<bool>,
|
||||||
|
{
|
||||||
|
self.disable_notification = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply_to_message_id<T: Into<i32>>(mut self, val: T) -> Self {
|
pub fn reply_to_message_id<T>(mut self, value: T) -> Self
|
||||||
self.reply_to_message_id = Some(val.into());
|
where
|
||||||
|
T: Into<i32>,
|
||||||
|
{
|
||||||
|
self.reply_to_message_id = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply_markup<T: Into<ReplyMarkup>>(mut self, val: T) -> Self {
|
pub fn reply_markup<T>(mut self, value: T) -> Self
|
||||||
self.reply_markup = Some(val.into());
|
where
|
||||||
|
T: Into<ReplyMarkup>,
|
||||||
|
{
|
||||||
|
self.reply_markup = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,9 @@ use async_trait::async_trait;
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{
|
requests::{
|
||||||
form_builder::FormBuilder, ChatId, Request, RequestContext,
|
form_builder::FormBuilder, Request, RequestContext, ResponseResult,
|
||||||
ResponseResult,
|
|
||||||
},
|
},
|
||||||
types::{InputFile, Message, ParseMode, ReplyMarkup},
|
types::{ChatId, InputFile, Message, ParseMode, ReplyMarkup},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -33,7 +32,7 @@ pub struct SendPhoto<'a> {
|
||||||
/// or inline URLs] in the media caption.
|
/// or inline URLs] in the media caption.
|
||||||
///
|
///
|
||||||
/// [Markdown]: crate::types::ParseMode::Markdown
|
/// [Markdown]: crate::types::ParseMode::Markdown
|
||||||
/// [Html]: crate::types::ParseMode::Html
|
/// [HTML]: crate::types::ParseMode::HTML
|
||||||
/// [bold, italic, fixed-width text or inline URLs]:
|
/// [bold, italic, fixed-width text or inline URLs]:
|
||||||
/// crate::types::ParseMode
|
/// crate::types::ParseMode
|
||||||
pub parse_mode: Option<ParseMode>,
|
pub parse_mode: Option<ParseMode>,
|
||||||
|
@ -74,28 +73,31 @@ impl SendPhoto<'_> {
|
||||||
InputFile::Url(url) => params.add("photo", &url),
|
InputFile::Url(url) => params.add("photo", &url),
|
||||||
InputFile::FileId(file_id) => params.add("photo", &file_id),
|
InputFile::FileId(file_id) => params.add("photo", &file_id),
|
||||||
};
|
};
|
||||||
let params = params.build();
|
|
||||||
|
|
||||||
network::request_multipart(
|
network::request_multipart(
|
||||||
&self.ctx.client,
|
&self.ctx.client,
|
||||||
&self.ctx.token,
|
&self.ctx.token,
|
||||||
"sendPhoto",
|
"sendPhoto",
|
||||||
Some(params),
|
Some(params.build()),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SendPhoto<'a> {
|
impl<'a> SendPhoto<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<C, P>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
photo: InputFile,
|
photo: P,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
P: Into<InputFile>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
photo,
|
photo: photo.into(),
|
||||||
caption: None,
|
caption: None,
|
||||||
parse_mode: None,
|
parse_mode: None,
|
||||||
disable_notification: None,
|
disable_notification: None,
|
||||||
|
@ -104,39 +106,51 @@ impl<'a> SendPhoto<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T: Into<ChatId>>(mut self, chat_id: T) -> Self {
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
self.chat_id = chat_id.into();
|
where
|
||||||
|
T: Into<ChatId>,
|
||||||
|
{
|
||||||
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn photo<T: Into<InputFile>>(mut self, photo: T) -> Self {
|
pub fn photo<T>(mut self, value: T) -> Self
|
||||||
self.photo = photo.into();
|
where
|
||||||
|
T: Into<InputFile>,
|
||||||
|
{
|
||||||
|
self.photo = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn caption<T: Into<String>>(mut self, caption: T) -> Self {
|
pub fn caption<T>(mut self, value: T) -> Self
|
||||||
self.caption = Some(caption.into());
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
{
|
||||||
|
self.caption = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_mode<T: Into<ParseMode>>(mut self, parse_mode: T) -> Self {
|
pub fn parse_mode<T>(mut self, value: T) -> Self
|
||||||
self.parse_mode = Some(parse_mode.into());
|
where
|
||||||
|
T: Into<ParseMode>,
|
||||||
|
{
|
||||||
|
self.parse_mode = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_notification<T: Into<bool>>(
|
pub fn disable_notification<T>(mut self, value: T) -> Self
|
||||||
mut self,
|
where
|
||||||
disable_notification: T,
|
T: Into<bool>,
|
||||||
) -> Self {
|
{
|
||||||
self.disable_notification = Some(disable_notification.into());
|
self.disable_notification = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply_to_message_id<T: Into<i32>>(
|
pub fn reply_to_message_id<T>(mut self, value: T) -> Self
|
||||||
mut self,
|
where
|
||||||
reply_to_message_id: T,
|
T: Into<i32>,
|
||||||
) -> Self {
|
{
|
||||||
self.reply_to_message_id = Some(reply_to_message_id.into());
|
self.reply_to_message_id = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{ChatId, Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
types::{Message, ReplyMarkup},
|
types::{ChatId, Message, ReplyMarkup},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Use this method to send a native poll. A native poll can't be sent to a
|
/// Use this method to send a native poll. A native poll can't be sent to a
|
||||||
|
@ -54,68 +54,73 @@ impl SendPoll<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SendPoll<'a> {
|
impl<'a> SendPoll<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<C, Q, O>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
question: String,
|
question: Q,
|
||||||
options: Vec<String>,
|
options: O,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
Q: Into<String>,
|
||||||
|
O: Into<Vec<String>>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
question,
|
question: question.into(),
|
||||||
options,
|
options: options.into(),
|
||||||
disable_notification: None,
|
disable_notification: None,
|
||||||
reply_to_message_id: None,
|
reply_to_message_id: None,
|
||||||
reply_markup: None,
|
reply_markup: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T>(mut self, chat_id: T) -> Self
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ChatId>,
|
T: Into<ChatId>,
|
||||||
{
|
{
|
||||||
self.chat_id = chat_id.into();
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn question<T>(mut self, question: T) -> Self
|
pub fn question<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
self.question = question.into();
|
self.question = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn options<T>(mut self, options: T) -> Self
|
pub fn options<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<Vec<String>>,
|
T: Into<Vec<String>>,
|
||||||
{
|
{
|
||||||
self.options = options.into();
|
self.options = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_notification<T>(mut self, disable_notification: T) -> Self
|
pub fn disable_notification<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
T: Into<bool>,
|
||||||
{
|
{
|
||||||
self.disable_notification = Some(disable_notification.into());
|
self.disable_notification = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply_to_message_id<T>(mut self, reply_to_message_id: T) -> Self
|
pub fn reply_to_message_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<i32>,
|
T: Into<i32>,
|
||||||
{
|
{
|
||||||
self.reply_to_message_id = Some(reply_to_message_id.into());
|
self.reply_to_message_id = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply_markup<T>(mut self, reply_markup: T) -> Self
|
pub fn reply_markup<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ReplyMarkup>,
|
T: Into<ReplyMarkup>,
|
||||||
{
|
{
|
||||||
self.reply_markup = Some(reply_markup.into());
|
self.reply_markup = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{ChatId, Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
types::{Message, ReplyMarkup},
|
types::{ChatId, Message, ReplyMarkup},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Use this method to send information about a venue.
|
/// Use this method to send information about a venue.
|
||||||
|
@ -69,21 +69,28 @@ impl SendVenue<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SendVenue<'a> {
|
impl<'a> SendVenue<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<Lt, Lg, C, T, A>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
latitude: f64,
|
latitude: Lt,
|
||||||
longitude: f64,
|
longitude: Lg,
|
||||||
title: String,
|
title: T,
|
||||||
address: String,
|
address: A,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
Lt: Into<f64>,
|
||||||
|
Lg: Into<f64>,
|
||||||
|
C: Into<ChatId>,
|
||||||
|
T: Into<String>,
|
||||||
|
A: Into<String>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
latitude,
|
latitude: latitude.into(),
|
||||||
longitude,
|
longitude: longitude.into(),
|
||||||
title,
|
title: title.into(),
|
||||||
address,
|
address: address.into(),
|
||||||
foursquare_id: None,
|
foursquare_id: None,
|
||||||
foursquare_type: None,
|
foursquare_type: None,
|
||||||
disable_notification: None,
|
disable_notification: None,
|
||||||
|
@ -91,75 +98,75 @@ impl<'a> SendVenue<'a> {
|
||||||
reply_markup: None,
|
reply_markup: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn chat_id<T>(mut self, chat_id: T) -> Self
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ChatId>,
|
T: Into<ChatId>,
|
||||||
{
|
{
|
||||||
self.chat_id = chat_id.into();
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn longitude<T>(mut self, longitude: T) -> Self
|
pub fn longitude<Lg>(mut self, value: Lg) -> Self
|
||||||
where
|
where
|
||||||
T: Into<f64>,
|
Lg: Into<f64>,
|
||||||
{
|
{
|
||||||
self.longitude = longitude.into();
|
self.longitude = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn latitude<T>(mut self, latitude: T) -> Self
|
pub fn latitude<Lt>(mut self, value: Lt) -> Self
|
||||||
where
|
where
|
||||||
T: Into<f64>,
|
Lt: Into<f64>,
|
||||||
{
|
{
|
||||||
self.latitude = latitude.into();
|
self.latitude = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn title<T>(mut self, title: T) -> Self
|
pub fn title<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
self.title = title.into();
|
self.title = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn address<T>(mut self, address: T) -> Self
|
pub fn address<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
self.address = address.into();
|
self.address = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn foursquare_id<T>(mut self, foursquare_id: T) -> Self
|
pub fn foursquare_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
self.foursquare_id = Some(foursquare_id.into());
|
self.foursquare_id = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_notification<T>(mut self, disable_notification: T) -> Self
|
pub fn disable_notification<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
T: Into<bool>,
|
||||||
{
|
{
|
||||||
self.disable_notification = Some(disable_notification.into());
|
self.disable_notification = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn foursquare_type<T>(mut self, foursquare_type: T) -> Self
|
pub fn foursquare_type<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
self.foursquare_type = Some(foursquare_type.into());
|
self.foursquare_type = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply_markup<T>(mut self, reply_markup: T) -> Self
|
pub fn reply_markup<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ReplyMarkup>,
|
T: Into<ReplyMarkup>,
|
||||||
{
|
{
|
||||||
self.reply_markup = Some(reply_markup.into());
|
self.reply_markup = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,202 @@
|
||||||
use crate::requests::RequestContext;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
///TODO: add implementation
|
use crate::network;
|
||||||
|
use crate::requests::{Request, RequestContext, ResponseResult};
|
||||||
|
use crate::types::{ChatId, Message, ParseMode, ReplyMarkup};
|
||||||
|
|
||||||
|
//TODO: add action to bot api
|
||||||
|
///Use this method to send video files, Telegram clients support mp4 videos
|
||||||
|
/// (other formats may be sent as Document). On success, the sent Message is
|
||||||
|
/// returned. Bots can currently send video files of up to 50 MB in size, this
|
||||||
|
/// limit may be changed in the future.
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub struct SendVideo<'a> {
|
pub struct SendVideo<'a> {
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
|
///Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format @channelusername)
|
||||||
|
pub chat_id: ChatId,
|
||||||
|
///Video to send. Pass a file_id as String to send a video that exists on
|
||||||
|
/// the Telegram servers (recommended), pass an HTTP URL as a String for
|
||||||
|
/// Telegram to get a video from the Internet, or upload a new video using
|
||||||
|
/// multipart/form-data. More info on Sending Files »
|
||||||
|
pub video: String,
|
||||||
|
///Duration of sent video in seconds
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub duration: Option<u64>,
|
||||||
|
///Video width
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub width: Option<i32>,
|
||||||
|
///Video height
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub height: Option<i32>,
|
||||||
|
///Thumbnail of the file sent; can be ignored if thumbnail generation for
|
||||||
|
/// the file is supported server-side. The thumbnail should be in JPEG
|
||||||
|
/// format and less than 200 kB in size. A thumbnail‘s width and height
|
||||||
|
/// should not exceed 320. Ignored if the file is not uploaded using
|
||||||
|
/// multipart/form-data. Thumbnails can’t be reused and can be only
|
||||||
|
/// uploaded as a new file, so you can pass “attach://<file_attach_name>”
|
||||||
|
/// if the thumbnail was uploaded using multipart/form-data under
|
||||||
|
/// <file_attach_name>. More info on Sending Files »
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub thumb: Option<String>,
|
||||||
|
//InputFile or String
|
||||||
|
///Video caption (may also be used when resending videos by file_id),
|
||||||
|
/// 0-1024 characters
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub 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.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub parse_mode: Option<ParseMode>,
|
||||||
|
///Pass True, if the uploaded video is suitable for streaming
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub supports_streaming: Option<bool>,
|
||||||
|
/// Sends the message silently. Users will receive a notification with no
|
||||||
|
/// sound.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub disable_notification: Option<bool>,
|
||||||
|
///If the message is a reply, ID of the original message
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub reply_to_message_id: Option<i32>,
|
||||||
|
///Additional interface options. A JSON-serialized object for an inline
|
||||||
|
/// keyboard, custom reply keyboard, instructions to remove reply keyboard
|
||||||
|
/// or to force a reply from the user.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub reply_markup: Option<ReplyMarkup>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Request for SendVideo<'_> {
|
||||||
|
type ReturnValue = Message;
|
||||||
|
|
||||||
|
async fn send_boxed(self) -> ResponseResult<Self::ReturnValue> {
|
||||||
|
self.send().await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SendVideo<'_> {
|
||||||
|
async fn send(self) -> ResponseResult<Message> {
|
||||||
|
network::request_json(
|
||||||
|
&self.ctx.client,
|
||||||
|
&self.ctx.token,
|
||||||
|
"sendVideo",
|
||||||
|
&self,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> SendVideo<'a> {
|
||||||
|
pub(crate) fn new<C, V>(
|
||||||
|
ctx: RequestContext<'a>,
|
||||||
|
chat_id: C,
|
||||||
|
video: V,
|
||||||
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
V: Into<String>,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
ctx,
|
||||||
|
chat_id: chat_id.into(),
|
||||||
|
video: video.into(),
|
||||||
|
duration: None,
|
||||||
|
width: None,
|
||||||
|
height: None,
|
||||||
|
thumb: None,
|
||||||
|
caption: None,
|
||||||
|
parse_mode: None,
|
||||||
|
supports_streaming: None,
|
||||||
|
disable_notification: None,
|
||||||
|
reply_to_message_id: None,
|
||||||
|
reply_markup: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<ChatId>,
|
||||||
|
{
|
||||||
|
self.chat_id = value.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn video<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
{
|
||||||
|
self.video = value.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn duration<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<u64>,
|
||||||
|
{
|
||||||
|
self.duration = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn width<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<i32>,
|
||||||
|
{
|
||||||
|
self.width = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn height<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<i32>,
|
||||||
|
{
|
||||||
|
self.height = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn thumb<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
{
|
||||||
|
self.thumb = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn caption<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
{
|
||||||
|
self.caption = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn parse_mode<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<ParseMode>,
|
||||||
|
{
|
||||||
|
self.parse_mode = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn supports_streaming<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<bool>,
|
||||||
|
{
|
||||||
|
self.supports_streaming = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn disable_notification<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<bool>,
|
||||||
|
{
|
||||||
|
self.disable_notification = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn reply_to_message_id<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<i32>,
|
||||||
|
{
|
||||||
|
self.reply_to_message_id = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn reply_markup<T>(mut self, value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<ReplyMarkup>,
|
||||||
|
{
|
||||||
|
self.reply_markup = Some(value.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
use crate::network;
|
|
||||||
use crate::requests::{ChatId, Request, RequestContext, ResponseResult};
|
|
||||||
use crate::types::{Message, ReplyMarkup};
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
network,
|
||||||
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
|
types::{ChatId, Message, ReplyMarkup},
|
||||||
|
};
|
||||||
|
|
||||||
///As of v.4.0, Telegram clients support rounded square mp4 videos of up to 1
|
///As of v.4.0, Telegram clients support rounded square mp4 videos of up to 1
|
||||||
/// minute long. Use this method to send video messages. On success, the sent
|
/// minute long. Use this method to send video messages. On success, the sent
|
||||||
/// Message is returned.
|
/// Message is returned.
|
||||||
|
@ -17,7 +20,8 @@ pub struct SendVideoNote<'a> {
|
||||||
/// exists on the Telegram servers (recommended) or upload a new video
|
/// exists on the Telegram servers (recommended) or upload a new video
|
||||||
/// using multipart/form-data. More info on Sending Files ». Sending video
|
/// using multipart/form-data. More info on Sending Files ». Sending video
|
||||||
/// notes by a URL is currently unsupported
|
/// notes by a URL is currently unsupported
|
||||||
pub video_note: String, // InputFile or String
|
pub video_note: String,
|
||||||
|
// InputFile or String
|
||||||
///Duration of sent video in seconds
|
///Duration of sent video in seconds
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub duration: Option<u64>,
|
pub duration: Option<u64>,
|
||||||
|
@ -33,7 +37,8 @@ pub struct SendVideoNote<'a> {
|
||||||
/// if the thumbnail was uploaded using multipart/form-data under
|
/// if the thumbnail was uploaded using multipart/form-data under
|
||||||
/// <file_attach_name>. More info on Sending Files »
|
/// <file_attach_name>. More info on Sending Files »
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub thumb: Option<String>, // InputFile or String
|
pub thumb: Option<String>,
|
||||||
|
// InputFile or String
|
||||||
///Sends the message silently. Users will receive a notification with no
|
///Sends the message silently. Users will receive a notification with no
|
||||||
/// sound.
|
/// sound.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
@ -70,15 +75,19 @@ impl SendVideoNote<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SendVideoNote<'a> {
|
impl<'a> SendVideoNote<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<C, V>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
video_note: String,
|
video_note: V,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
V: Into<String>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
video_note,
|
video_note: video_note.into(),
|
||||||
duration: None,
|
duration: None,
|
||||||
length: None,
|
length: None,
|
||||||
thumb: None,
|
thumb: None,
|
||||||
|
@ -88,67 +97,67 @@ impl<'a> SendVideoNote<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T>(mut self, chat_id: T) -> Self
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ChatId>,
|
T: Into<ChatId>,
|
||||||
{
|
{
|
||||||
self.chat_id = chat_id.into();
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn video_note<T>(mut self, video_note: T) -> Self
|
pub fn video_note<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
self.video_note = video_note.into();
|
self.video_note = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn duration<T>(mut self, duration: T) -> Self
|
pub fn duration<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<u64>,
|
T: Into<u64>,
|
||||||
{
|
{
|
||||||
self.duration = Some(duration.into());
|
self.duration = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn length<T>(mut self, length: T) -> Self
|
pub fn length<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<u64>,
|
T: Into<u64>,
|
||||||
{
|
{
|
||||||
self.length = Some(length.into());
|
self.length = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thumb<T>(mut self, thumb: T) -> Self
|
pub fn thumb<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
self.thumb = Some(thumb.into());
|
self.thumb = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_notification<T>(mut self, disable_notification: T) -> Self
|
pub fn disable_notification<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
T: Into<bool>,
|
||||||
{
|
{
|
||||||
self.disable_notification = Some(disable_notification.into());
|
self.disable_notification = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply_to_message_id<T>(mut self, reply_to_message_id: T) -> Self
|
pub fn reply_to_message_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<i32>,
|
T: Into<i32>,
|
||||||
{
|
{
|
||||||
self.reply_to_message_id = Some(reply_to_message_id.into());
|
self.reply_to_message_id = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply_markup<T>(mut self, reply_markup: T) -> Self
|
pub fn reply_markup<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ReplyMarkup>,
|
T: Into<ReplyMarkup>,
|
||||||
{
|
{
|
||||||
self.reply_markup = Some(reply_markup.into());
|
self.reply_markup = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
use crate::network;
|
|
||||||
use crate::requests::{ChatId, Request, RequestContext, ResponseResult};
|
|
||||||
use crate::types::{Message, ReplyMarkup, ParseMode};
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
network,
|
||||||
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
|
types::{ChatId, Message, ParseMode, ReplyMarkup},
|
||||||
|
};
|
||||||
|
|
||||||
///Use this method to send audio files, if you want Telegram clients to display
|
///Use this method to send audio files, if you want Telegram clients to display
|
||||||
/// the file as a playable voice message. For this to work, your audio must be
|
/// the file as a playable voice message. For this to work, your audio must be
|
||||||
/// in an .ogg file encoded with OPUS (other formats may be sent as Audio or
|
/// in an .ogg file encoded with OPUS (other formats may be sent as Audio or
|
||||||
|
@ -20,7 +23,8 @@ pub struct SendVoice<'a> {
|
||||||
/// on the Telegram servers (recommended), pass an HTTP URL as a String for
|
/// on the Telegram servers (recommended), pass an HTTP URL as a String for
|
||||||
/// Telegram to get a file from the Internet, or upload a new one using
|
/// Telegram to get a file from the Internet, or upload a new one using
|
||||||
/// multipart/form-data. More info on Sending Files »
|
/// multipart/form-data. More info on Sending Files »
|
||||||
pub voice: String, //InputFile or String
|
pub voice: String,
|
||||||
|
//InputFile or String
|
||||||
/// Voice message caption, 0-1024 characters
|
/// Voice message caption, 0-1024 characters
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub caption: Option<String>,
|
pub caption: Option<String>,
|
||||||
|
@ -68,15 +72,19 @@ impl SendVoice<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SendVoice<'a> {
|
impl<'a> SendVoice<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<C, V>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
voice: String,
|
voice: V,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
V: Into<String>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
voice,
|
voice: voice.into(),
|
||||||
caption: None,
|
caption: None,
|
||||||
parse_mode: None,
|
parse_mode: None,
|
||||||
duration: None,
|
duration: None,
|
||||||
|
@ -86,70 +94,67 @@ impl<'a> SendVoice<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T>(mut self, chat_id: T) -> Self
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ChatId>,
|
T: Into<ChatId>,
|
||||||
{
|
{
|
||||||
self.chat_id = chat_id.into();
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn voice<T>(mut self, voice: T) -> Self
|
pub fn voice<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
self.voice = voice.into();
|
self.voice = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn caption<T>(mut self, caption: T) -> Self
|
pub fn caption<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
self.caption = Some(caption.into());
|
self.caption = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_mode<T>(mut self, parse_mode: T) -> Self
|
pub fn parse_mode<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ParseMode>,
|
T: Into<ParseMode>,
|
||||||
{
|
{
|
||||||
self.parse_mode = Some(parse_mode.into());
|
self.parse_mode = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn duration<T>(mut self, value: T) -> Self
|
||||||
pub fn duration<T>(mut self, duration: T) -> Self
|
|
||||||
where
|
where
|
||||||
T: Into<u64>,
|
T: Into<u64>,
|
||||||
{
|
{
|
||||||
self.duration = Some(duration.into());
|
self.duration = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_notification<T>(mut self, disable_notification: T) -> Self
|
pub fn disable_notification<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<bool>,
|
T: Into<bool>,
|
||||||
{
|
{
|
||||||
self.disable_notification = Some(disable_notification.into());
|
self.disable_notification = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply_to_message_id<T>(mut self, reply_to_message_id: T) -> Self
|
pub fn reply_to_message_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<i32>,
|
T: Into<i32>,
|
||||||
{
|
{
|
||||||
self.reply_to_message_id = Some(reply_to_message_id.into());
|
self.reply_to_message_id = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reply_markup<T>(mut self, value: T) -> Self
|
||||||
pub fn reply_markup<T>(mut self, reply_markup: T) -> Self
|
|
||||||
where
|
where
|
||||||
T: Into<ReplyMarkup>,
|
T: Into<ReplyMarkup>,
|
||||||
{
|
{
|
||||||
self.reply_markup = Some(reply_markup.into());
|
self.reply_markup = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{ChatId, Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
types::{InlineKeyboardMarkup, Message},
|
types::{ChatId, InlineKeyboardMarkup, Message},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Use this method to stop updating a live location message before live_period
|
/// Use this method to stop updating a live location message before live_period
|
||||||
|
@ -64,35 +64,35 @@ impl<'a> StopMessageLiveLocation<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T>(mut self, chat_id: T) -> Self
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ChatId>,
|
T: Into<ChatId>,
|
||||||
{
|
{
|
||||||
self.chat_id = Some(chat_id.into());
|
self.chat_id = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn message_id<T>(mut self, message_id: T) -> Self
|
pub fn message_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<i32>,
|
T: Into<i32>,
|
||||||
{
|
{
|
||||||
self.message_id = Some(message_id.into());
|
self.message_id = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inline_message_id<T>(mut self, inline_message_id: T) -> Self
|
pub fn inline_message_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<String>,
|
T: Into<String>,
|
||||||
{
|
{
|
||||||
self.inline_message_id = Some(inline_message_id.into());
|
self.inline_message_id = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply_markup<T>(mut self, reply_markup: T) -> Self
|
pub fn reply_markup<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<InlineKeyboardMarkup>,
|
T: Into<InlineKeyboardMarkup>,
|
||||||
{
|
{
|
||||||
self.reply_markup = Some(reply_markup.into());
|
self.reply_markup = Some(value.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::network;
|
use crate::{
|
||||||
use crate::requests::{ChatId, Request, RequestContext, ResponseResult};
|
network,
|
||||||
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
|
types::ChatId,
|
||||||
|
};
|
||||||
|
|
||||||
/// Use this method to unban a previously kicked user in a supergroup or
|
/// Use this method to unban a previously kicked user in a supergroup or
|
||||||
/// channel. The user will not return to the group or channel automatically, but
|
/// channel. The user will not return to the group or channel automatically, but
|
||||||
|
@ -40,31 +43,35 @@ impl UnbanChatMember<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> UnbanChatMember<'a> {
|
impl<'a> UnbanChatMember<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new<C, U>(
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
chat_id: ChatId,
|
chat_id: C,
|
||||||
user_id: i32,
|
user_id: U,
|
||||||
) -> Self {
|
) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
U: Into<i32>,
|
||||||
|
{
|
||||||
Self {
|
Self {
|
||||||
ctx,
|
ctx,
|
||||||
chat_id,
|
chat_id: chat_id.into(),
|
||||||
user_id,
|
user_id: user_id.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T>(mut self, chat_id: T) -> Self
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ChatId>,
|
T: Into<ChatId>,
|
||||||
{
|
{
|
||||||
self.chat_id = chat_id.into();
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn user_id<T>(mut self, user_id: T) -> Self
|
pub fn user_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<i32>,
|
T: Into<i32>,
|
||||||
{
|
{
|
||||||
self.user_id = user_id.into();
|
self.user_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{ChatId, Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
types::True,
|
types::{ChatId, True},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
@ -36,15 +36,21 @@ impl UnpinChatMessage<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> UnpinChatMessage<'a> {
|
impl<'a> UnpinChatMessage<'a> {
|
||||||
pub(crate) fn new(ctx: RequestContext<'a>, chat_id: ChatId) -> Self {
|
pub(crate) fn new<C>(ctx: RequestContext<'a>, value: C) -> Self
|
||||||
Self { ctx, chat_id }
|
where
|
||||||
|
C: Into<ChatId>,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
ctx,
|
||||||
|
chat_id: value.into(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_id<T>(mut self, chat_id: T) -> Self
|
pub fn chat_id<T>(mut self, value: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<ChatId>,
|
T: Into<ChatId>,
|
||||||
{
|
{
|
||||||
self.chat_id = chat_id.into();
|
self.chat_id = value.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use bytes::{Bytes, BytesMut};
|
use bytes::{Bytes, BytesMut};
|
||||||
use reqwest::r#async::multipart::Part;
|
use reqwest::{multipart::Part, Body};
|
||||||
use tokio::{codec::FramedRead, prelude::*};
|
use tokio::{codec::FramedRead, prelude::*};
|
||||||
|
|
||||||
struct FileDecoder;
|
struct FileDecoder;
|
||||||
|
@ -30,12 +30,11 @@ pub fn file_to_part(path_to_file: &PathBuf) -> Part {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.flatten_stream();
|
.flatten_stream();
|
||||||
let part = Part::stream(file).file_name(
|
Part::stream(Body::wrap_stream(file)).file_name(
|
||||||
path_to_file
|
path_to_file
|
||||||
.file_name()
|
.file_name()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
.into_owned(),
|
.into_owned(),
|
||||||
);
|
)
|
||||||
part
|
|
||||||
}
|
}
|
||||||
|
|
14
src/types/chat_action.rs
Normal file
14
src/types/chat_action.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#[derive(Debug, Serialize, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum ChatAction {
|
||||||
|
Typing,
|
||||||
|
UploadPhoto,
|
||||||
|
RecordVideo,
|
||||||
|
UploadVideo,
|
||||||
|
RecordAudio,
|
||||||
|
UploadAudio,
|
||||||
|
UploadDocument,
|
||||||
|
FindLocation,
|
||||||
|
RecordVideoNote,
|
||||||
|
UploadVideoNote,
|
||||||
|
}
|
36
src/types/chat_id.rs
Normal file
36
src/types/chat_id.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/// Unique identifier for the target chat or username of the target channel (in
|
||||||
|
/// the format @channelusername)
|
||||||
|
#[derive(Debug, Display, Serialize, From, PartialEq, Eq, Clone)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum ChatId {
|
||||||
|
/// chat identifier
|
||||||
|
#[display(fmt = "{}", _0)]
|
||||||
|
Id(i64),
|
||||||
|
/// _channel_ username (in the format @channelusername)
|
||||||
|
#[display(fmt = "{}", _0)]
|
||||||
|
ChannelUsername(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chat_id_id_serialization() {
|
||||||
|
let expected_json = String::from(r#"123456"#);
|
||||||
|
let actual_json = serde_json::to_string(&ChatId::Id(123456)).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(expected_json, actual_json)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chat_id_channel_username_serialization() {
|
||||||
|
let expected_json = String::from(r#""@username""#);
|
||||||
|
let actual_json = serde_json::to_string(&ChatId::ChannelUsername(
|
||||||
|
String::from("@username"),
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(expected_json, actual_json)
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,5 +14,7 @@ pub struct ForceReply {
|
||||||
/// users only. Targets: 1) users that are @mentioned in the text of the
|
/// users only. Targets: 1) users that are @mentioned in the text of the
|
||||||
/// [`Message`] object; 2) if the bot's message is a reply
|
/// [`Message`] object; 2) if the bot's message is a reply
|
||||||
/// (has reply_to_message_id), sender of the original message.
|
/// (has reply_to_message_id), sender of the original message.
|
||||||
|
///
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
pub selective: Option<bool>,
|
pub selective: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,15 +44,13 @@ pub enum InlineKeyboardButtonKind {
|
||||||
/// Build buttons
|
/// Build buttons
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ```edition2018
|
/// ```
|
||||||
/// use async_telegram_bot::types::InlineKeyboardButton;
|
/// use async_telegram_bot::types::InlineKeyboardButton;
|
||||||
///
|
///
|
||||||
/// fn main() {
|
|
||||||
/// let url_button = InlineKeyboardButton::url(
|
/// let url_button = InlineKeyboardButton::url(
|
||||||
/// "Text".to_string(),
|
/// "Text".to_string(),
|
||||||
/// "http://url.com".to_string(),
|
/// "http://url.com".to_string(),
|
||||||
/// );
|
/// );
|
||||||
/// }
|
|
||||||
/// ```
|
/// ```
|
||||||
impl InlineKeyboardButton {
|
impl InlineKeyboardButton {
|
||||||
pub fn url(text: String, url: String) -> InlineKeyboardButton {
|
pub fn url(text: String, url: String) -> InlineKeyboardButton {
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::types::InlineKeyboardButton;
|
||||||
///
|
///
|
||||||
/// *Note*: This will only work in Telegram versions released after
|
/// *Note*: This will only work in Telegram versions released after
|
||||||
/// 9 April, 2016. Older clients will display unsupported message.
|
/// 9 April, 2016. Older clients will display unsupported message.
|
||||||
#[derive(Debug, Serialize, Deserialize, Hash, PartialEq, Eq, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Hash, PartialEq, Eq, Clone, Default)]
|
||||||
pub struct InlineKeyboardMarkup {
|
pub struct InlineKeyboardMarkup {
|
||||||
/// Array of button rows, each represented by an Array of
|
/// Array of button rows, each represented by an Array of
|
||||||
/// [`InlineKeyboardButton`] objects
|
/// [`InlineKeyboardButton`] objects
|
||||||
|
@ -28,9 +28,7 @@ pub struct InlineKeyboardMarkup {
|
||||||
/// ```
|
/// ```
|
||||||
impl InlineKeyboardMarkup {
|
impl InlineKeyboardMarkup {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
<_>::default()
|
||||||
inline_keyboard: vec![],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append_row(mut self, buttons: Vec<InlineKeyboardButton>) -> Self {
|
pub fn append_row(mut self, buttons: Vec<InlineKeyboardButton>) -> Self {
|
||||||
|
|
|
@ -19,7 +19,7 @@ pub enum InputMedia {
|
||||||
/// or inline URLs] in the media caption.
|
/// or inline URLs] in the media caption.
|
||||||
///
|
///
|
||||||
/// [Markdown]: crate::types::ParseMode::Markdown
|
/// [Markdown]: crate::types::ParseMode::Markdown
|
||||||
/// [Html]: crate::types::ParseMode::Html
|
/// [HTML]: crate::types::ParseMode::HTML
|
||||||
/// [bold, italic, fixed-width text or inline URLs]:
|
/// [bold, italic, fixed-width text or inline URLs]:
|
||||||
/// crate::types::ParseMode
|
/// crate::types::ParseMode
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
@ -45,7 +45,7 @@ pub enum InputMedia {
|
||||||
/// or inline URLs] in the media caption.
|
/// or inline URLs] in the media caption.
|
||||||
///
|
///
|
||||||
/// [Markdown]: crate::types::ParseMode::Markdown
|
/// [Markdown]: crate::types::ParseMode::Markdown
|
||||||
/// [Html]: crate::types::ParseMode::Html
|
/// [HTML]: crate::types::ParseMode::HTML
|
||||||
/// [bold, italic, fixed-width text or inline URLs]:
|
/// [bold, italic, fixed-width text or inline URLs]:
|
||||||
/// crate::types::ParseMode
|
/// crate::types::ParseMode
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
@ -85,7 +85,7 @@ pub enum InputMedia {
|
||||||
/// or inline URLs] in the media caption.
|
/// or inline URLs] in the media caption.
|
||||||
///
|
///
|
||||||
/// [Markdown]: crate::types::ParseMode::Markdown
|
/// [Markdown]: crate::types::ParseMode::Markdown
|
||||||
/// [Html]: crate::types::ParseMode::Html
|
/// [HTML]: crate::types::ParseMode::HTML
|
||||||
/// [bold, italic, fixed-width text or inline URLs]:
|
/// [bold, italic, fixed-width text or inline URLs]:
|
||||||
/// crate::types::ParseMode
|
/// crate::types::ParseMode
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
@ -121,7 +121,7 @@ pub enum InputMedia {
|
||||||
/// or inline URLs] in the media caption.
|
/// or inline URLs] in the media caption.
|
||||||
///
|
///
|
||||||
/// [Markdown]: crate::types::ParseMode::Markdown
|
/// [Markdown]: crate::types::ParseMode::Markdown
|
||||||
/// [Html]: crate::types::ParseMode::Html
|
/// [HTML]: crate::types::ParseMode::HTML
|
||||||
/// [bold, italic, fixed-width text or inline URLs]:
|
/// [bold, italic, fixed-width text or inline URLs]:
|
||||||
/// crate::types::ParseMode
|
/// crate::types::ParseMode
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
@ -157,7 +157,7 @@ pub enum InputMedia {
|
||||||
/// or inline URLs] in the media caption.
|
/// or inline URLs] in the media caption.
|
||||||
///
|
///
|
||||||
/// [Markdown]: crate::types::ParseMode::Markdown
|
/// [Markdown]: crate::types::ParseMode::Markdown
|
||||||
/// [Html]: crate::types::ParseMode::Html
|
/// [HTML]: crate::types::ParseMode::HTML
|
||||||
/// [bold, italic, fixed-width text or inline URLs]:
|
/// [bold, italic, fixed-width text or inline URLs]:
|
||||||
/// crate::types::ParseMode
|
/// crate::types::ParseMode
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
|
|
@ -19,7 +19,7 @@ pub enum InputMessageContent {
|
||||||
/// or inline URLs] in the media caption.
|
/// or inline URLs] in the media caption.
|
||||||
///
|
///
|
||||||
/// [Markdown]: crate::types::ParseMode::Markdown
|
/// [Markdown]: crate::types::ParseMode::Markdown
|
||||||
/// [Html]: crate::types::ParseMode::Html
|
/// [HTML]: crate::types::ParseMode::HTML
|
||||||
/// [bold, italic, fixed-width text or inline URLs]:
|
/// [bold, italic, fixed-width text or inline URLs]:
|
||||||
/// crate::types::ParseMode
|
/// crate::types::ParseMode
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
use crate::types::{
|
use crate::types::{Animation, Audio, Chat, Contact, Document, Game, InlineKeyboardMarkup, Invoice, Location, MessageEntity, PassportData, PhotoSize, Poll, Sticker, SuccessfulPayment, User, Venue, Video, VideoNote, Voice, True};
|
||||||
Animation, Audio, Chat, Contact, Document, Game, InlineKeyboardMarkup,
|
|
||||||
Invoice, Location, MessageEntity, PassportData, PhotoSize, Poll, Sticker,
|
|
||||||
SuccessfulPayment, User, Venue, Video, VideoNote, Voice,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Clone)]
|
#[derive(Debug, Deserialize, PartialEq, Clone)]
|
||||||
pub struct Message {
|
pub struct Message {
|
||||||
|
@ -14,19 +10,6 @@ pub struct Message {
|
||||||
pub kind: MessageKind,
|
pub kind: MessageKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Message {
|
|
||||||
pub fn text(&self) -> Option<&str> {
|
|
||||||
if let MessageKind::Common {
|
|
||||||
media_kind: MediaKind::Text { ref text, .. },
|
|
||||||
..
|
|
||||||
} = self.kind
|
|
||||||
{
|
|
||||||
Some(text)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Clone)]
|
#[derive(Debug, Deserialize, PartialEq, Clone)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
|
@ -54,16 +37,16 @@ pub enum MessageKind {
|
||||||
new_chat_photo: Vec<PhotoSize>,
|
new_chat_photo: Vec<PhotoSize>,
|
||||||
},
|
},
|
||||||
DeleteChatPhoto {
|
DeleteChatPhoto {
|
||||||
delete_chat_photo: bool,
|
delete_chat_photo: True,
|
||||||
},
|
},
|
||||||
GroupChatCreated {
|
GroupChatCreated {
|
||||||
group_chat_created: bool,
|
group_chat_created: True,
|
||||||
},
|
},
|
||||||
SupergroupChatCreated {
|
SupergroupChatCreated {
|
||||||
supergroup_chat_created: bool,
|
supergroup_chat_created: True,
|
||||||
},
|
},
|
||||||
ChannelChatCreated {
|
ChannelChatCreated {
|
||||||
channel_chat_created: bool,
|
channel_chat_created: True,
|
||||||
},
|
},
|
||||||
Migrate {
|
Migrate {
|
||||||
migrate_to_chat_id: i64,
|
migrate_to_chat_id: i64,
|
||||||
|
@ -201,6 +184,375 @@ pub enum MediaKind {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod getters {
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
use crate::types::{
|
||||||
|
self, Message, Sender, User, ForwardedFrom, Chat, MessageEntity,
|
||||||
|
PhotoSize, True,
|
||||||
|
message::{
|
||||||
|
MessageKind::{
|
||||||
|
Common, NewChatMembers, LeftChatMember, NewChatTitle,
|
||||||
|
NewChatPhoto, DeleteChatPhoto, GroupChatCreated,
|
||||||
|
ChannelChatCreated, Migrate, Invoice, SuccessfulPayment,
|
||||||
|
ConnectedWebsite, PassportData
|
||||||
|
},
|
||||||
|
MediaKind::{
|
||||||
|
Text, Video, Photo, Animation, Audio, Document, Voice, Game,
|
||||||
|
Sticker, VideoNote, Contact, Location, Poll, Venue
|
||||||
|
},
|
||||||
|
ForwardKind::{NonChannelForward, ChannelForward, Origin}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use crate::types::message::MessageKind::{SupergroupChatCreated, Pinned};
|
||||||
|
|
||||||
|
/// Getters for [Message] fields from [telegram docs].
|
||||||
|
///
|
||||||
|
/// [Message]: crate::types::Message
|
||||||
|
/// [telegram docs]: https://core.telegram.org/bots/api#message
|
||||||
|
impl Message {
|
||||||
|
/// NOTE: this is getter for both `from` and `author_signature`
|
||||||
|
pub fn from(&self) -> Option<&Sender> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { from, .. } => Some(from),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// NOTE: this is getter for both `forward_from` and
|
||||||
|
/// `forward_sender_name`
|
||||||
|
pub fn forward_from(&self) -> Option<&ForwardedFrom> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { forward_kind: NonChannelForward { from, .. }, .. } =>
|
||||||
|
Some(from),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn forward_from_chat(&self) -> Option<&Chat> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { forward_kind: ChannelForward { chat, .. }, .. } =>
|
||||||
|
Some(chat),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn forward_from_message_id(&self) -> Option<&i32> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { forward_kind: ChannelForward { message_id, .. }, .. } =>
|
||||||
|
Some(message_id),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn forward_signature(&self) -> Option<&str> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { forward_kind: ChannelForward { signature, .. }, .. } =>
|
||||||
|
signature.as_ref().map(Deref::deref),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn forward_date(&self) -> Option<&i32> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { forward_kind: ChannelForward { date, .. }, .. } |
|
||||||
|
Common { forward_kind: NonChannelForward { date, .. }, .. } =>
|
||||||
|
Some(date),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reply_to_message(&self) -> Option<&Message> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { forward_kind: Origin { reply_to_message, .. }, .. } =>
|
||||||
|
reply_to_message.as_ref().map(Deref::deref),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn edit_date(&self) -> Option<&i32> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { edit_date, .. } => edit_date.as_ref(),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn media_group_id(&self) -> Option<&str> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Video { media_group_id, .. }, .. } |
|
||||||
|
Common { media_kind: Photo { media_group_id, .. }, .. } =>
|
||||||
|
media_group_id.as_ref().map(Deref::deref),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn text(&self) -> Option<&str> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Text { text, .. }, .. } => Some(text),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn entities(&self) -> Option<&[MessageEntity]> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Text { entities, .. }, .. } =>
|
||||||
|
Some(entities),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn caption_entities(&self) -> Option<&[MessageEntity]> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Animation { caption_entities, .. }, .. } |
|
||||||
|
Common { media_kind: Audio { caption_entities, .. }, .. } |
|
||||||
|
Common { media_kind: Document { caption_entities, .. }, .. } |
|
||||||
|
Common { media_kind: Photo { caption_entities, .. }, .. } |
|
||||||
|
Common { media_kind: Video { caption_entities, .. }, .. } |
|
||||||
|
Common { media_kind: Voice { caption_entities, .. }, .. } =>
|
||||||
|
Some(caption_entities),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn audio(&self) -> Option<&types::Audio> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Audio { audio, .. }, .. } => Some(audio),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn document(&self) -> Option<&types::Document> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Document { document, .. }, .. } =>
|
||||||
|
Some(document),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn animation(&self) -> Option<&types::Animation> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Animation { animation, .. }, .. } =>
|
||||||
|
Some(animation),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn game(&self) -> Option<&types::Game> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Game { game, .. }, .. } => Some(game),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn photo(&self) -> Option<&[PhotoSize]> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Photo { photo, .. }, .. } => Some(photo),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sticker(&self) -> Option<&types::Sticker> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Sticker { sticker, .. }, .. } =>
|
||||||
|
Some(sticker),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn video(&self) -> Option<&types::Video> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Video { video, .. }, .. } => Some(video),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn voice(&self) -> Option<&types::Voice> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Voice { voice, .. }, .. } => Some(voice),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn video_note(&self) -> Option<&types::VideoNote> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: VideoNote { video_note, .. }, .. } =>
|
||||||
|
Some(video_note),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn caption(&self) -> Option<&str> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind, .. } => match media_kind {
|
||||||
|
Animation { caption, ..} |
|
||||||
|
Audio { caption, ..} |
|
||||||
|
Document { caption, ..} |
|
||||||
|
Photo { caption, ..} |
|
||||||
|
Video { caption, ..} |
|
||||||
|
Voice { caption, ..} => caption.as_ref().map(Deref::deref),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contact(&self) -> Option<&types::Contact> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Contact { contact }, .. } => Some(contact),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn location(&self) -> Option<&types::Location> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Location { location, .. }, .. } =>
|
||||||
|
Some(location),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn venue(&self) -> Option<&types::Venue> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Venue { venue, .. }, .. } => Some(venue),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poll(&self) -> Option<&types::Poll> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { media_kind: Poll { poll, .. }, .. } => Some(poll),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_chat_members(&self) -> Option<&[User]> {
|
||||||
|
match &self.kind {
|
||||||
|
NewChatMembers { new_chat_members } => Some(new_chat_members),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn left_chat_member(&self) -> Option<&User> {
|
||||||
|
match &self.kind {
|
||||||
|
LeftChatMember { left_chat_member } => Some(left_chat_member),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_chat_title(&self) -> Option<&str> {
|
||||||
|
match &self.kind {
|
||||||
|
NewChatTitle { new_chat_title } => Some(new_chat_title),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_chat_photo(&self) -> Option<&[PhotoSize]> {
|
||||||
|
match &self.kind {
|
||||||
|
NewChatPhoto { new_chat_photo } => Some(new_chat_photo),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: OK, `Option<True>` is weird, can we do something with it?
|
||||||
|
// mb smt like `is_delete_chat_photo(&self) -> bool`?
|
||||||
|
pub fn delete_chat_photo(&self) -> Option<True> {
|
||||||
|
match &self.kind {
|
||||||
|
DeleteChatPhoto { delete_chat_photo } =>
|
||||||
|
Some(*delete_chat_photo),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn group_chat_created(&self) -> Option<True> {
|
||||||
|
match &self.kind {
|
||||||
|
GroupChatCreated { group_chat_created } =>
|
||||||
|
Some(*group_chat_created),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn super_group_chat_created(&self) -> Option<True> {
|
||||||
|
match &self.kind {
|
||||||
|
SupergroupChatCreated { supergroup_chat_created } =>
|
||||||
|
Some(*supergroup_chat_created),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn channel_chat_created(&self) -> Option<True> {
|
||||||
|
match &self.kind {
|
||||||
|
ChannelChatCreated { channel_chat_created } =>
|
||||||
|
Some(*channel_chat_created),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn migrate_to_chat_id(&self) -> Option<&i64> {
|
||||||
|
match &self.kind {
|
||||||
|
Migrate { migrate_to_chat_id, .. } => Some(migrate_to_chat_id),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn migrate_from_chat_id(&self) -> Option<&i64> {
|
||||||
|
match &self.kind {
|
||||||
|
Migrate { migrate_from_chat_id, .. } =>
|
||||||
|
Some(migrate_from_chat_id),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pinned_message(&self) -> Option<&Message> {
|
||||||
|
match &self.kind {
|
||||||
|
Pinned { pinned } => Some(pinned),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn invoice(&self) -> Option<&types::Invoice> {
|
||||||
|
match &self.kind {
|
||||||
|
Invoice { invoice } => Some(invoice),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn successful_payment(&self) -> Option<&types::SuccessfulPayment> {
|
||||||
|
match &self.kind {
|
||||||
|
SuccessfulPayment { successful_payment } =>
|
||||||
|
Some(successful_payment),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn connected_website(&self) -> Option<&str> {
|
||||||
|
match &self.kind {
|
||||||
|
ConnectedWebsite { connected_website } =>
|
||||||
|
Some(connected_website),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn passport_data(&self) -> Option<&types::PassportData> {
|
||||||
|
match &self.kind {
|
||||||
|
PassportData { passport_data } => Some(passport_data),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn reply_markup(&self) -> Option<&types::InlineKeyboardMarkup> {
|
||||||
|
match &self.kind {
|
||||||
|
Common { reply_markup, .. } => reply_markup.as_ref(),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use serde_json::from_str;
|
use serde_json::from_str;
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use self::not_implemented_types::*;
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
animation::Animation,
|
animation::Animation,
|
||||||
audio::Audio,
|
audio::Audio,
|
||||||
callback_game::CallbackGame,
|
callback_game::CallbackGame,
|
||||||
callback_query::CallbackQuery,
|
callback_query::CallbackQuery,
|
||||||
chat::{Chat, ChatKind, NonPrivateChatKind},
|
chat::{Chat, ChatKind, NonPrivateChatKind},
|
||||||
|
chat_action::ChatAction,
|
||||||
|
chat_id::ChatId,
|
||||||
chat_member::{ChatMember, ChatMemberStatus},
|
chat_member::{ChatMember, ChatMemberStatus},
|
||||||
chat_permissions::ChatPermissions,
|
chat_permissions::ChatPermissions,
|
||||||
chat_photo::ChatPhoto,
|
chat_photo::ChatPhoto,
|
||||||
|
@ -90,6 +91,8 @@ mod audio;
|
||||||
mod callback_game;
|
mod callback_game;
|
||||||
mod callback_query;
|
mod callback_query;
|
||||||
mod chat;
|
mod chat;
|
||||||
|
mod chat_action;
|
||||||
|
mod chat_id;
|
||||||
mod chat_member;
|
mod chat_member;
|
||||||
mod chat_permissions;
|
mod chat_permissions;
|
||||||
mod chat_photo;
|
mod chat_photo;
|
||||||
|
@ -113,7 +116,6 @@ mod login_url;
|
||||||
mod mask_position;
|
mod mask_position;
|
||||||
mod message;
|
mod message;
|
||||||
mod message_entity;
|
mod message_entity;
|
||||||
mod not_implemented_types;
|
|
||||||
mod order_info;
|
mod order_info;
|
||||||
mod parse_mode;
|
mod parse_mode;
|
||||||
mod photo_size;
|
mod photo_size;
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Serialize, Clone)]
|
|
||||||
pub struct PassportData;
|
|
|
@ -28,16 +28,16 @@ use serde::{Deserialize, Serialize};
|
||||||
///
|
///
|
||||||
/// Use the following syntax in your message:
|
/// Use the following syntax in your message:
|
||||||
///
|
///
|
||||||
/// ```ignore
|
/// <pre>
|
||||||
/// *bold text*
|
/// *bold text*
|
||||||
/// _italic text_
|
/// _italic text_
|
||||||
/// [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)
|
||||||
/// `inline fixed-width code`
|
/// `inline fixed-width code`
|
||||||
/// ```block_language
|
/// ```block_language
|
||||||
/// pre-formatted fixed-width code block
|
/// pre-formatted fixed-width code block
|
||||||
/// ```
|
/// ```
|
||||||
/// ```
|
/// </pre>
|
||||||
///
|
///
|
||||||
/// ## 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 when using
|
||||||
|
@ -45,14 +45,14 @@ use serde::{Deserialize, Serialize};
|
||||||
///
|
///
|
||||||
/// The following tags are currently supported:
|
/// The following tags are currently supported:
|
||||||
///
|
///
|
||||||
/// ```ignore
|
/// <pre>
|
||||||
/// <b>bold</b>, <strong>bold</strong>
|
/// <b>bold</b>, <strong>bold</strong>
|
||||||
/// <i>italic</i>, <em>italic</em>
|
/// <i>italic</i>, <em>italic</em>
|
||||||
/// <a href="http://www.example.com/">inline URL</a>
|
/// <a href="http://www.example.com/">inline URL</a>
|
||||||
/// <a href="tg://user?id=123456789">inline mention of a user</a>
|
/// <a href="tg://user?id=123456789">inline mention of a user</a>
|
||||||
/// <code>inline fixed-width code</code>
|
/// <code>inline fixed-width code</code>
|
||||||
/// <pre>pre-formatted fixed-width code block</pre>
|
/// <pre>pre-formatted fixed-width code block</pre>
|
||||||
/// ```
|
/// </pre>
|
||||||
///
|
///
|
||||||
/// Please note:
|
/// Please note:
|
||||||
///
|
///
|
||||||
|
@ -64,6 +64,10 @@ use serde::{Deserialize, Serialize};
|
||||||
/// - All numerical HTML entities are supported.
|
/// - All numerical HTML entities are supported.
|
||||||
/// - The API currently supports only the following named HTML entities: `<`,
|
/// - The API currently supports only the following named HTML entities: `<`,
|
||||||
/// `>`, `&` and `"`.
|
/// `>`, `&` and `"`.
|
||||||
|
///
|
||||||
|
/// [Markdown]: crate::types::ParseMode::Markdown
|
||||||
|
/// [HTML]: crate::types::ParseMode::HTML
|
||||||
|
/// [SendMessage]: crate::requests::SendMessage
|
||||||
pub enum ParseMode {
|
pub enum ParseMode {
|
||||||
HTML,
|
HTML,
|
||||||
Markdown,
|
Markdown,
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Serialize, Clone)]
|
||||||
/// This object represents one size of a photo or a [`Document`] /
|
/// This object represents one size of a photo or a [`Document`] /
|
||||||
/// [`Sticker`] thumbnail.
|
/// [`Sticker`] thumbnail.
|
||||||
|
///
|
||||||
|
/// [`Document`]: crate::types::Document
|
||||||
|
/// [`Sticker`]: crate::types::Sticker
|
||||||
pub struct PhotoSize {
|
pub struct PhotoSize {
|
||||||
/// Identifier for this file
|
/// Identifier for this file
|
||||||
pub file_id: String,
|
pub file_id: String,
|
||||||
|
|
|
@ -5,6 +5,8 @@ use crate::types::KeyboardButton;
|
||||||
pub struct ReplyKeyboardMarkup {
|
pub struct ReplyKeyboardMarkup {
|
||||||
/// Array of button rows, each represented by an Array of
|
/// Array of button rows, each represented by an Array of
|
||||||
/// [`KeyboardButton`] objects
|
/// [`KeyboardButton`] objects
|
||||||
|
///
|
||||||
|
/// [`KeyboardButton`]: crate::types::KeyboardButton
|
||||||
pub keyboard: Vec<Vec<KeyboardButton>>,
|
pub keyboard: Vec<Vec<KeyboardButton>>,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
@ -32,5 +34,7 @@ pub struct ReplyKeyboardMarkup {
|
||||||
/// Example: A user requests to change the bot‘s language, bot replies to
|
/// Example: A user requests to change the bot‘s language, bot replies to
|
||||||
/// the request with a keyboard to select the new language. Other users in
|
/// the request with a keyboard to select the new language. Other users in
|
||||||
/// the group don’t see the keyboard.
|
/// the group don’t see the keyboard.
|
||||||
|
///
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
pub selective: Option<bool>,
|
pub selective: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
/// By default, custom keyboards are displayed until a new keyboard is sent
|
/// By default, custom keyboards are displayed until a new keyboard is sent
|
||||||
/// by a bot. An exception is made for one-time keyboards that are hidden
|
/// by a bot. An exception is made for one-time keyboards that are hidden
|
||||||
/// immediately after the user presses a button (see [`ReplyKeyboardMarkup`]).
|
/// immediately after the user presses a button (see [`ReplyKeyboardMarkup`]).
|
||||||
|
///
|
||||||
|
/// [`ReplyKeyboardMarkup`]: crate::types::ReplyKeyboardMarkup
|
||||||
#[derive(Debug, Serialize, Deserialize, Hash, PartialEq, Eq, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Hash, PartialEq, Eq, Clone)]
|
||||||
pub struct ReplyKeyboardRemove {
|
pub struct ReplyKeyboardRemove {
|
||||||
/// equests clients to remove the custom keyboard (user will not be able to
|
/// equests clients to remove the custom keyboard (user will not be able to
|
||||||
|
@ -19,5 +21,7 @@ pub struct ReplyKeyboardRemove {
|
||||||
/// Example: A user requests to change the bot‘s language, bot replies to
|
/// Example: A user requests to change the bot‘s language, bot replies to
|
||||||
/// the request with a keyboard to select the new language. Other users in
|
/// the request with a keyboard to select the new language. Other users in
|
||||||
/// the group don’t see the keyboard.
|
/// the group don’t see the keyboard.
|
||||||
|
///
|
||||||
|
/// [`Message`]: crate::types::Message
|
||||||
pub selective: Option<bool>,
|
pub selective: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::requests::ChatId;
|
use crate::types::{ChatId, InlineKeyboardMarkup, LabeledPrice};
|
||||||
use crate::types::{InlineKeyboardMarkup, LabeledPrice};
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct SendInvoice {
|
pub struct SendInvoice {
|
||||||
|
|
|
@ -4,16 +4,11 @@ use serde::ser::{Serialize, Serializer};
|
||||||
#[derive(Copy, Clone, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
#[derive(Copy, Clone, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct True;
|
pub struct True;
|
||||||
|
|
||||||
impl std::process::Termination for True {
|
|
||||||
fn report(self) -> i32 {
|
|
||||||
libc::EXIT_SUCCESS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::convert::TryFrom<bool> for True {
|
impl std::convert::TryFrom<bool> for True {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
fn try_from(value: bool) -> Result<Self, Self::Error> {
|
fn try_from(value: bool) -> Result<Self, Self::Error> {
|
||||||
|
#[allow(clippy::match_bool)]
|
||||||
match value {
|
match value {
|
||||||
true => Ok(True),
|
true => Ok(True),
|
||||||
false => Err(()),
|
false => Err(()),
|
||||||
|
@ -43,6 +38,7 @@ impl<'de> Visitor<'de> for TrueVisitor {
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
|
#[allow(clippy::match_bool)]
|
||||||
match value {
|
match value {
|
||||||
true => Ok(True),
|
true => Ok(True),
|
||||||
false => Err(E::custom("expected `true`, found `false`")),
|
false => Err(E::custom("expected `true`, found `false`")),
|
||||||
|
|
Loading…
Reference in a new issue