mirror of
https://github.com/teloxide/teloxide.git
synced 2024-12-23 06:51:01 +01:00
Merge branch 'dev' into unbox_send_future
This commit is contained in:
commit
8b1a032b55
21 changed files with 529 additions and 52 deletions
|
@ -16,3 +16,4 @@ tokio = "0.2.0-alpha.4"
|
||||||
bytes = "0.4.12"
|
bytes = "0.4.12"
|
||||||
futures-preview = "0.3.0-alpha.18"
|
futures-preview = "0.3.0-alpha.18"
|
||||||
async-trait = "0.1.13"
|
async-trait = "0.1.13"
|
||||||
|
libc = "0.2.62"
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
bot::Bot,
|
bot::Bot,
|
||||||
requests::{
|
requests::{
|
||||||
edit_message_live_location::EditMessageLiveLocation,
|
ChatId, EditMessageLiveLocation, ForwardMessage, GetFile, GetMe,
|
||||||
forward_message::ForwardMessage, get_file::GetFile, get_me::GetMe,
|
SendAudio, SendLocation, SendMediaGroup, SendMessage, SendPhoto,
|
||||||
send_audio::SendAudio, send_location::SendLocation,
|
StopMessageLiveLocation,
|
||||||
send_media_group::SendMediaGroup, send_message::SendMessage,
|
|
||||||
send_photo::SendPhoto,
|
|
||||||
stop_message_live_location::StopMessageLiveLocation, ChatId,
|
|
||||||
},
|
},
|
||||||
types::{InputFile, InputMedia},
|
types::{InputFile, InputMedia},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
|
#![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;
|
||||||
|
|
||||||
mod network;
|
mod network;
|
||||||
|
mod errors;
|
||||||
|
|
||||||
pub mod bot;
|
pub mod bot;
|
||||||
pub mod errors;
|
|
||||||
pub mod requests;
|
pub mod requests;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
use bytes::Buf;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use reqwest::r#async::{Chunk, Client};
|
use reqwest::r#async::{Chunk, Client};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
io::{AsyncWrite, AsyncWriteExt},
|
io::{AsyncWrite, AsyncWriteExt},
|
||||||
stream::Stream,
|
stream::Stream,
|
||||||
};
|
};
|
||||||
use bytes::Buf;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network::{file_url, TELEGRAM_API_URL},
|
network::{file_url, TELEGRAM_API_URL},
|
||||||
|
@ -23,7 +23,8 @@ where
|
||||||
let mut stream = download_file_stream(client, token, path).await?;
|
let mut stream = download_file_stream(client, token, path).await?;
|
||||||
|
|
||||||
while let Some(chunk) = stream.next().await {
|
while let Some(chunk) = stream.next().await {
|
||||||
destination.write_all(chunk?.bytes()).await?;
|
let chunk = chunk?;
|
||||||
|
destination.write_all(chunk.bytes()).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -3,7 +3,7 @@ use reqwest::r#async::{multipart::Form, Client, Response};
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network::{method_url, TELEGRAM_API_URL, TelegramResponse},
|
network::{method_url, TelegramResponse, TELEGRAM_API_URL},
|
||||||
requests::ResponseResult,
|
requests::ResponseResult,
|
||||||
RequestError,
|
RequestError,
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@ use async_trait::async_trait;
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
|
types::True
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Clone)]
|
#[derive(Debug, Serialize, Clone)]
|
||||||
|
@ -35,7 +36,7 @@ pub struct AnswerPreCheckoutQuery<'a> {
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Request for AnswerPreCheckoutQuery<'_> {
|
impl Request for AnswerPreCheckoutQuery<'_> {
|
||||||
type ReturnValue = bool;
|
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
|
||||||
|
@ -43,7 +44,7 @@ impl Request for AnswerPreCheckoutQuery<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnswerPreCheckoutQuery<'_> {
|
impl AnswerPreCheckoutQuery<'_> {
|
||||||
pub async fn send(self) -> ResponseResult<bool> {
|
pub async fn send(self) -> ResponseResult<True> {
|
||||||
network::request_json(
|
network::request_json(
|
||||||
&self.ctx.client,
|
&self.ctx.client,
|
||||||
&self.ctx.token,
|
&self.ctx.token,
|
||||||
|
|
|
@ -3,7 +3,7 @@ use async_trait::async_trait;
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{Request, RequestContext, ResponseResult},
|
requests::{Request, RequestContext, ResponseResult},
|
||||||
types::ShippingOption,
|
types::{ShippingOption, True},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
@ -37,7 +37,7 @@ pub struct AnswerShippingQuery<'a> {
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Request for AnswerShippingQuery<'_> {
|
impl Request for AnswerShippingQuery<'_> {
|
||||||
type ReturnValue = bool;
|
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,19 +1,73 @@
|
||||||
use crate::requests::RequestContext;
|
use crate::network;
|
||||||
|
use crate::requests::{Request, RequestContext, RequestFuture, ResponseResult};
|
||||||
|
use crate::types::UserProfilePhotos;
|
||||||
|
|
||||||
//TODO: complete implementation after user_profile_fotos will be added to
|
|
||||||
// types/mod.rs
|
|
||||||
///Use this method to get a list of profile pictures for a user. Returns a
|
///Use this method to get a list of profile pictures for a user. Returns a
|
||||||
/// UserProfilePhotos object.
|
/// UserProfilePhotos object.
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
struct GetUserProfilePhotos<'a> {
|
pub struct GetUserProfilePhotos<'a> {
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
/// Unique identifier of the target user
|
/// Unique identifier of the target user
|
||||||
user_id: i32,
|
pub user_id: i32,
|
||||||
/// Sequential number of the first photo to be returned. By default, all
|
/// Sequential number of the first photo to be returned. By default, all
|
||||||
/// photos are returned.
|
/// photos are returned.
|
||||||
offset: Option<i64>,
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub offset: Option<i64>,
|
||||||
///Limits the number of photos to be retrieved. Values between 1—100 are
|
///Limits the number of photos to be retrieved. Values between 1—100 are
|
||||||
/// accepted. Defaults to 100.
|
/// accepted. Defaults to 100.
|
||||||
limit: Option<i64>,
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub limit: Option<i64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Request<'a> for GetUserProfilePhotos<'a> {
|
||||||
|
type ReturnValue = UserProfilePhotos;
|
||||||
|
|
||||||
|
fn send(self) -> RequestFuture<'a, ResponseResult<Self::ReturnValue>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
network::request_json(
|
||||||
|
&self.ctx.client,
|
||||||
|
&self.ctx.token,
|
||||||
|
"getUserProfilePhotos",
|
||||||
|
&self,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> GetUserProfilePhotos<'a> {
|
||||||
|
pub fn new(ctx: RequestContext<'a>, user_id: i32) -> Self {
|
||||||
|
Self {
|
||||||
|
ctx,
|
||||||
|
user_id,
|
||||||
|
offset: None,
|
||||||
|
limit: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn user_id<T>(mut self, user_id: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<i32>,
|
||||||
|
{
|
||||||
|
self.user_id = user_id.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn offset<T>(mut self, offset: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<i64>,
|
||||||
|
{
|
||||||
|
self.offset = Some(offset.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn limit<T>(mut self, limit: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<i64>,
|
||||||
|
{
|
||||||
|
self.limit = Some(limit.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,72 @@
|
||||||
use crate::requests::RequestContext;
|
use crate::network;
|
||||||
//TODO:: need implementation
|
use crate::requests::{
|
||||||
|
ChatId, Request, RequestContext, RequestFuture, ResponseResult,
|
||||||
|
};
|
||||||
|
use crate::types::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
|
||||||
/// the case of supergroups and channels, the user will not be able to return to
|
/// the case of supergroups and channels, the user will not be able to return to
|
||||||
/// the group on their own using invite links, etc., unless unbanned first. The
|
/// the group on their own using invite links, etc., unless unbanned first. 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. Returns True on success.
|
/// appropriate admin rights. Returns True on success.
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
struct KickChatMember<'a> {
|
pub struct KickChatMember<'a> {
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
|
///Unique identifier for the target group or username of the target
|
||||||
|
/// supergroup or channel (in the format @channelusername)
|
||||||
|
pub chat_id: ChatId,
|
||||||
|
/// Unique identifier of the target user
|
||||||
|
pub user_id: i32,
|
||||||
|
///Date when the user will be unbanned, unix time. If user is banned for
|
||||||
|
/// more than 366 days or less than 30 seconds from the current time they
|
||||||
|
/// are considered to be banned forever
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub until_date: Option<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Request<'a> for KickChatMember<'a> {
|
||||||
|
type ReturnValue = True;
|
||||||
|
|
||||||
|
fn send(self) -> RequestFuture<'a, ResponseResult<Self::ReturnValue>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
network::request_json(
|
||||||
|
self.ctx.client,
|
||||||
|
self.ctx.token,
|
||||||
|
"kickChatMember",
|
||||||
|
&self,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> KickChatMember<'a> {
|
||||||
|
pub(crate) fn new(
|
||||||
|
ctx: RequestContext<'a>,
|
||||||
|
chat_id: ChatId,
|
||||||
|
user_id: i32,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
ctx,
|
||||||
|
chat_id,
|
||||||
|
user_id,
|
||||||
|
until_date: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn chat_id<T: Into<ChatId>>(mut self, chat_id: T) -> Self {
|
||||||
|
self.chat_id = chat_id.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn user_id<T: Into<i32>>(mut self, user_id: T) -> Self {
|
||||||
|
self.user_id = user_id.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn until_date<T: Into<u64>>(mut self, until_date: T) -> Self {
|
||||||
|
self.until_date = Some(until_date.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,23 @@ use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
use crate::RequestError;
|
use crate::RequestError;
|
||||||
|
|
||||||
|
pub use self::{
|
||||||
|
answer_pre_checkout_query::AnswerPreCheckoutQuery,
|
||||||
|
answer_shipping_query::AnswerShippingQuery,
|
||||||
|
edit_message_live_location::EditMessageLiveLocation,
|
||||||
|
forward_message::ForwardMessage, get_chat::GetChat, get_file::GetFile,
|
||||||
|
get_me::GetMe, get_updates::GetUpdates,
|
||||||
|
get_user_profile_photos::GetUserProfilePhotos,
|
||||||
|
kick_chat_member::KickChatMember, pin_chat_message::PinChatMessage,
|
||||||
|
restrict_chat_member::RestrictChatMember,
|
||||||
|
send_audio::SendAudio, send_chat_action::SendChatAction,
|
||||||
|
send_contact::SendContact, send_location::SendLocation,
|
||||||
|
send_media_group::SendMediaGroup, send_message::SendMessage,
|
||||||
|
send_photo::SendPhoto, send_poll::SendPoll, send_venue::SendVenue,
|
||||||
|
stop_message_live_location::StopMessageLiveLocation,
|
||||||
|
unban_chat_member::UnbanChatMember,
|
||||||
|
};
|
||||||
|
|
||||||
pub type ResponseResult<T> = Result<T, RequestError>;
|
pub type ResponseResult<T> = Result<T, RequestError>;
|
||||||
|
|
||||||
/// Request that can be sent to telegram.
|
/// Request that can be sent to telegram.
|
||||||
|
@ -62,25 +79,26 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod answer_pre_checkout_query;
|
mod answer_pre_checkout_query;
|
||||||
pub mod answer_shipping_query;
|
mod answer_shipping_query;
|
||||||
pub mod edit_message_live_location;
|
mod edit_message_live_location;
|
||||||
pub mod forward_message;
|
mod forward_message;
|
||||||
pub mod get_chat;
|
mod get_chat;
|
||||||
pub mod get_file;
|
mod get_file;
|
||||||
pub mod get_me;
|
mod get_me;
|
||||||
pub mod get_updates;
|
mod get_updates;
|
||||||
pub mod get_user_profile_photos;
|
mod get_user_profile_photos;
|
||||||
pub mod kick_chat_member;
|
mod kick_chat_member;
|
||||||
pub mod restrict_chat_member;
|
mod pin_chat_message;
|
||||||
pub mod send_audio;
|
mod restrict_chat_member;
|
||||||
pub mod send_chat_action;
|
mod send_audio;
|
||||||
pub mod send_contact;
|
mod send_chat_action;
|
||||||
pub mod send_location;
|
mod send_contact;
|
||||||
pub mod send_media_group;
|
mod send_location;
|
||||||
pub mod send_message;
|
mod send_media_group;
|
||||||
pub mod send_photo;
|
mod send_message;
|
||||||
pub mod send_poll;
|
mod send_photo;
|
||||||
pub mod send_venue;
|
mod send_poll;
|
||||||
pub mod stop_message_live_location;
|
mod send_venue;
|
||||||
pub mod unban_chat_member;
|
mod stop_message_live_location;
|
||||||
|
mod unban_chat_member;
|
||||||
|
|
50
src/requests/pin_chat_message.rs
Normal file
50
src/requests/pin_chat_message.rs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
use crate::{
|
||||||
|
requests::{ChatId, RequestContext, RequestFuture, ResponseResult, Request},
|
||||||
|
types::True
|
||||||
|
};
|
||||||
|
use crate::network;
|
||||||
|
|
||||||
|
/// Use this method to get up to date information about the chat
|
||||||
|
/// (current name of the user for one-on-one conversations,
|
||||||
|
/// current username of a user, group or channel, etc.).
|
||||||
|
/// Returns a Chat object on success.
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct PinChatMessage<'a> {
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
ctx: RequestContext<'a>,
|
||||||
|
/// Unique identifier for the target chat or username
|
||||||
|
/// of the target supergroup or channel (in the format @channelusername)
|
||||||
|
pub chat_id: ChatId,
|
||||||
|
pub message_id: i32,
|
||||||
|
pub disable_notification: Option<bool>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> PinChatMessage<'a> {
|
||||||
|
pub(crate) fn new(
|
||||||
|
ctx: RequestContext<'a>, chat_id: ChatId, message_id: i32
|
||||||
|
) -> Self {
|
||||||
|
Self { ctx, chat_id, message_id, disable_notification: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disable_notification<T>(mut self, val: T) -> Self
|
||||||
|
where T: Into<bool>
|
||||||
|
{
|
||||||
|
self.disable_notification = Some(val.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Request<'a> for PinChatMessage<'a> {
|
||||||
|
type ReturnValue = True;
|
||||||
|
|
||||||
|
fn send(self) -> RequestFuture<'a, ResponseResult<Self::ReturnValue>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
network::request_json(
|
||||||
|
&self.ctx.client,
|
||||||
|
&self.ctx.token,
|
||||||
|
"pinChatMessage",
|
||||||
|
&self,
|
||||||
|
).await
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,92 @@
|
||||||
use crate::requests::RequestContext;
|
use crate::network;
|
||||||
//TODO:: need implementation
|
use crate::requests::{
|
||||||
|
ChatId, Request, RequestContext, RequestFuture, ResponseResult,
|
||||||
|
};
|
||||||
|
use crate::types::{ChatPermissions, True};
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// appropriate admin rights. Pass True for all permissions to lift restrictions
|
||||||
|
/// from a user. Returns True on success.
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
struct RestrictChatMember<'a> {
|
pub struct RestrictChatMember<'a> {
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
|
///Unique identifier for the target chat or username of the target
|
||||||
|
/// supergroup (in the format @supergroupusername)
|
||||||
|
pub chat_id: ChatId,
|
||||||
|
///Unique identifier of the target user
|
||||||
|
pub user_id: i32,
|
||||||
|
///New user permissions
|
||||||
|
pub permissions: ChatPermissions,
|
||||||
|
///Date when restrictions will be lifted for the user, unix time. If user
|
||||||
|
/// is restricted for more than 366 days or less than 30 seconds from the
|
||||||
|
/// current time, they are considered to be restricted forever
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub until_date: Option<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Request<'a> for RestrictChatMember<'a> {
|
||||||
|
type ReturnValue = True;
|
||||||
|
|
||||||
|
fn send(self) -> RequestFuture<'a, ResponseResult<Self::ReturnValue>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
network::request_json(
|
||||||
|
&self.ctx.client,
|
||||||
|
&self.ctx.token,
|
||||||
|
"restrictChatMember",
|
||||||
|
&self,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> RestrictChatMember<'a> {
|
||||||
|
pub(crate) fn new(
|
||||||
|
ctx: RequestContext<'a>,
|
||||||
|
chat_id: ChatId,
|
||||||
|
user_id: i32,
|
||||||
|
permissions: ChatPermissions,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
ctx,
|
||||||
|
chat_id,
|
||||||
|
user_id,
|
||||||
|
permissions,
|
||||||
|
until_date: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn chat_id<T>(mut self, chat_id: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<ChatId>,
|
||||||
|
{
|
||||||
|
self.chat_id = chat_id.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn user_id<T>(mut self, user_id: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<i32>,
|
||||||
|
{
|
||||||
|
self.user_id = user_id.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn permissions<T>(mut self, permissions: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<ChatPermissions>,
|
||||||
|
{
|
||||||
|
self.permissions = permissions.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn until_date<T>(mut self, until_date: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<u64>,
|
||||||
|
{
|
||||||
|
self.until_date = Some(until_date.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use async_trait::async_trait;
|
||||||
use crate::{
|
use crate::{
|
||||||
network,
|
network,
|
||||||
requests::{ChatId, Request, RequestContext, ResponseResult},
|
requests::{ChatId, Request, RequestContext, ResponseResult},
|
||||||
|
types::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
|
||||||
|
@ -41,7 +42,7 @@ pub enum ChatAction {
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Request for SendChatAction<'_> {
|
impl Request for SendChatAction<'_> {
|
||||||
type ReturnValue = bool;
|
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
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::requests::RequestContext;
|
||||||
//TODO:: need implementation
|
//TODO:: need implementation
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
struct UnbanChatMember<'a> {
|
pub struct UnbanChatMember<'a> {
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
ctx: RequestContext<'a>,
|
ctx: RequestContext<'a>,
|
||||||
}
|
}
|
||||||
|
|
35
src/types/encrypted_credintials.rs
Normal file
35
src/types/encrypted_credintials.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Clone, Serialize)]
|
||||||
|
pub struct EncryptedCredentials {
|
||||||
|
// TODO: check base64 type
|
||||||
|
pub data: String,
|
||||||
|
pub hash: String,
|
||||||
|
pub secret: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn must_serialize_encrypted_credentials_to_json() {
|
||||||
|
// given
|
||||||
|
let expected_json = r#"
|
||||||
|
{
|
||||||
|
"data":"someData",
|
||||||
|
"hash":"1122",
|
||||||
|
"secret":"secret"
|
||||||
|
}"#
|
||||||
|
.replace("\n", "")
|
||||||
|
.replace(" ", "");
|
||||||
|
let encrypted_credentials = EncryptedCredentials {
|
||||||
|
data: "someData".to_string(),
|
||||||
|
hash: "1122".to_string(),
|
||||||
|
secret: "secret".to_string(),
|
||||||
|
};
|
||||||
|
// when
|
||||||
|
let actual_json =
|
||||||
|
serde_json::to_string(&encrypted_credentials).unwrap();
|
||||||
|
//then
|
||||||
|
assert_eq!(actual_json, expected_json)
|
||||||
|
}
|
||||||
|
}
|
67
src/types/encrypted_passport_element.rs
Normal file
67
src/types/encrypted_passport_element.rs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
use super::passport_file::PassportFile;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||||
|
pub struct EncryptedPassportElement {
|
||||||
|
pub hash: String,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub kind: EncryptedPassportElementKind
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum EncryptedPassportElementKind {
|
||||||
|
PersonalDetails {
|
||||||
|
data: String
|
||||||
|
},
|
||||||
|
Passport {
|
||||||
|
data: String,
|
||||||
|
front_side: PassportFile,
|
||||||
|
selfie: PassportFile,
|
||||||
|
translation: Option<Vec<PassportFile>>
|
||||||
|
},
|
||||||
|
DriverLicense {
|
||||||
|
data: String,
|
||||||
|
front_side: PassportFile,
|
||||||
|
reverse_side: PassportFile,
|
||||||
|
selfie: PassportFile,
|
||||||
|
translation: Option<Vec<PassportFile>>
|
||||||
|
},
|
||||||
|
IdentityCard {
|
||||||
|
data: String,
|
||||||
|
front_side: PassportFile,
|
||||||
|
reverse_side: PassportFile,
|
||||||
|
selfie: PassportFile,
|
||||||
|
translation: Option<Vec<PassportFile>>
|
||||||
|
},
|
||||||
|
InternalPassport {
|
||||||
|
data: String,
|
||||||
|
front_side: PassportFile,
|
||||||
|
selfie: PassportFile,
|
||||||
|
translation: Option<Vec<PassportFile>>
|
||||||
|
},
|
||||||
|
Address {
|
||||||
|
data: String
|
||||||
|
},
|
||||||
|
UtilityBill {
|
||||||
|
files: Vec<PassportFile>,
|
||||||
|
translation: Option<Vec<PassportFile>>
|
||||||
|
},
|
||||||
|
BankStatement {
|
||||||
|
files: Vec<PassportFile>,
|
||||||
|
translation: Option<Vec<PassportFile>>
|
||||||
|
},
|
||||||
|
RentalAgreement {
|
||||||
|
files: Vec<PassportFile>,
|
||||||
|
translation: Option<Vec<PassportFile>>
|
||||||
|
},
|
||||||
|
PassportRegistration {
|
||||||
|
files: Vec<PassportFile>,
|
||||||
|
translation: Option<Vec<PassportFile>>
|
||||||
|
},
|
||||||
|
TemporaryRegistration {
|
||||||
|
files: Vec<PassportFile>,
|
||||||
|
translation: Option<Vec<PassportFile>>
|
||||||
|
},
|
||||||
|
PhoneNumber { phone_number: String },
|
||||||
|
Email { email: String }
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ pub struct Message {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Message {
|
impl Message {
|
||||||
fn text(&self) -> Option<&str> {
|
pub fn text(&self) -> Option<&str> {
|
||||||
if let MessageKind::Common {
|
if let MessageKind::Common {
|
||||||
media_kind: MediaKind::Text { ref text, .. },
|
media_kind: MediaKind::Text { ref text, .. },
|
||||||
..
|
..
|
||||||
|
|
|
@ -11,6 +11,8 @@ pub use self::{
|
||||||
chosen_inline_result::ChosenInlineResult,
|
chosen_inline_result::ChosenInlineResult,
|
||||||
contact::Contact,
|
contact::Contact,
|
||||||
document::Document,
|
document::Document,
|
||||||
|
encrypted_credintials::EncryptedCredentials,
|
||||||
|
encrypted_passport_element::{EncryptedPassportElement, EncryptedPassportElementKind},
|
||||||
file::File,
|
file::File,
|
||||||
force_reply::ForceReply,
|
force_reply::ForceReply,
|
||||||
game::Game,
|
game::Game,
|
||||||
|
@ -54,6 +56,8 @@ pub use self::{
|
||||||
message_entity::MessageEntity,
|
message_entity::MessageEntity,
|
||||||
order_info::OrderInfo,
|
order_info::OrderInfo,
|
||||||
parse_mode::ParseMode,
|
parse_mode::ParseMode,
|
||||||
|
passport_data::PassportData,
|
||||||
|
passport_file::PassportFile,
|
||||||
photo_size::PhotoSize,
|
photo_size::PhotoSize,
|
||||||
poll::{Poll, PollOption},
|
poll::{Poll, PollOption},
|
||||||
pre_checkout_query::PreCheckoutQuery,
|
pre_checkout_query::PreCheckoutQuery,
|
||||||
|
@ -68,6 +72,7 @@ pub use self::{
|
||||||
sticker::Sticker,
|
sticker::Sticker,
|
||||||
sticker_set::StickerSet,
|
sticker_set::StickerSet,
|
||||||
successful_payment::SuccessfulPayment,
|
successful_payment::SuccessfulPayment,
|
||||||
|
unit_true::True,
|
||||||
update::{Update, UpdateKind},
|
update::{Update, UpdateKind},
|
||||||
user::User,
|
user::User,
|
||||||
user_profile_photos::UserProfilePhotos,
|
user_profile_photos::UserProfilePhotos,
|
||||||
|
@ -123,6 +128,7 @@ mod shipping_query;
|
||||||
mod sticker;
|
mod sticker;
|
||||||
mod sticker_set;
|
mod sticker_set;
|
||||||
mod successful_payment;
|
mod successful_payment;
|
||||||
|
mod unit_true;
|
||||||
mod update;
|
mod update;
|
||||||
mod user;
|
mod user;
|
||||||
mod user_profile_photos;
|
mod user_profile_photos;
|
||||||
|
@ -154,3 +160,8 @@ mod inline_query_result_photo;
|
||||||
mod inline_query_result_venue;
|
mod inline_query_result_venue;
|
||||||
mod inline_query_result_video;
|
mod inline_query_result_video;
|
||||||
mod inline_query_result_voice;
|
mod inline_query_result_voice;
|
||||||
|
|
||||||
|
mod encrypted_credintials;
|
||||||
|
mod encrypted_passport_element;
|
||||||
|
mod passport_data;
|
||||||
|
mod passport_file;
|
||||||
|
|
8
src/types/passport_data.rs
Normal file
8
src/types/passport_data.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
use super::encrypted_credintials::EncryptedCredentials;
|
||||||
|
use super::encrypted_passport_element::EncryptedPassportElement;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Clone, Serialize)]
|
||||||
|
pub struct PassportData {
|
||||||
|
pub data: Vec<EncryptedPassportElement>,
|
||||||
|
pub credentials: EncryptedCredentials,
|
||||||
|
}
|
6
src/types/passport_file.rs
Normal file
6
src/types/passport_file.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Clone, Serialize)]
|
||||||
|
pub struct PassportFile {
|
||||||
|
pub file_id: String,
|
||||||
|
pub file_size: u64,
|
||||||
|
pub file_date: u64,
|
||||||
|
}
|
81
src/types/unit_true.rs
Normal file
81
src/types/unit_true.rs
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
use serde::de::{self, Deserialize, Deserializer, Visitor};
|
||||||
|
use serde::ser::{Serialize, Serializer};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||||
|
pub struct True;
|
||||||
|
|
||||||
|
impl std::process::Termination for True {
|
||||||
|
fn report(self) -> i32 {
|
||||||
|
libc::EXIT_SUCCESS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::convert::TryFrom<bool> for True {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: bool) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
true => Ok(True),
|
||||||
|
false => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for True {
|
||||||
|
fn deserialize<D>(des: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>
|
||||||
|
{
|
||||||
|
des.deserialize_bool(TrueVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TrueVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for TrueVisitor {
|
||||||
|
type Value = True;
|
||||||
|
|
||||||
|
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
write!(f, "bool, equal to `true`")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: de::Error
|
||||||
|
{
|
||||||
|
match value {
|
||||||
|
true => Ok(True),
|
||||||
|
false => Err(E::custom("expected `true`, found `false`"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for True {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_bool(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::True;
|
||||||
|
use serde_json::{from_str, to_string};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unit_true_de() {
|
||||||
|
let json = "true";
|
||||||
|
let expected = True;
|
||||||
|
let actual = from_str(json).unwrap();
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unit_true_se() {
|
||||||
|
let actual = to_string(&True).unwrap();
|
||||||
|
let expected = "true";
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue