telegram_bot_fork/
api.rs

1use std::{rc::Rc, time::Duration};
2
3use futures::{future::result, Future};
4use tokio;
5use tokio_timer;
6
7use telegram_bot_fork_raw::{Request, ResponseType};
8
9use connector::Connector;
10use future::{NewTelegramFuture, TelegramFuture};
11use stream::{NewUpdatesStream, UpdatesStream};
12#[cfg(feature = "hyper_connector")]
13use {connector::default_connector, errors::Error};
14
15/// Main type for sending requests to the Telegram bot API.
16#[derive(Clone)]
17pub struct Api {
18    url: Option<String>,
19    inner: Rc<ApiInner>,
20}
21
22struct ApiInner {
23    token: String,
24    connector: Box<Connector>,
25}
26
27impl Api {
28    /// Start construction of the `Api` instance.
29    ///
30    /// # Examples
31    ///
32    /// Using default connector.
33    ///
34    /// ```rust
35    /// # extern crate telegram_bot_fork;
36    /// # extern crate tokio;
37    /// use telegram_bot_fork::Api;
38    ///
39    /// # fn main() {
40    /// # let telegram_token = "token";
41    /// let api = Api::new(telegram_token).unwrap();
42    /// # }
43    /// ```
44    ///
45    /// Using custom connector.
46    ///
47    ///
48    /// ```rust
49    /// # extern crate telegram_bot_fork;
50    /// # extern crate tokio;
51    /// # #[cfg(feature = "hyper_connector")]
52    /// # fn main() {
53    /// use telegram_bot_fork::{connector::hyper, Api};
54    ///
55    /// # let telegram_token = "token";
56    /// let api = Api::with_connector(telegram_token, hyper::default_connector().unwrap());
57    /// # }
58    ///
59    /// # #[cfg(not(feature = "hyper_connector"))]
60    /// # fn main() {}
61    /// ```
62    #[cfg(feature = "hyper_connector")]
63    pub fn new<T: AsRef<str>>(token: T) -> Result<Self, Error> {
64        Ok(Self::with_connector(token, default_connector()?))
65    }
66
67    pub fn with_connector<T: AsRef<str>>(token: T, connector: Box<Connector>) -> Self {
68        Api {
69            url: None,
70            inner: Rc::new(ApiInner {
71                token: token.as_ref().to_string(),
72                connector,
73            }),
74        }
75    }
76
77    pub fn set_url<T: AsRef<str>>(&mut self, url: T) -> &mut Self {
78        self.url = Some(url.as_ref().into());
79
80        self
81    }
82
83    /// Create a stream which produces updates from the Telegram server.
84    ///
85    /// # Examples
86    ///
87    /// ```rust
88    /// # extern crate futures;
89    /// # extern crate telegram_bot_fork;
90    /// # extern crate tokio;
91    /// # use telegram_bot_fork::Api;
92    /// # fn main() {
93    /// # let api: Api = Api::new("token").unwrap();
94    /// use futures::Stream;
95    ///
96    /// let future = api.stream().for_each(|update| {
97    ///     println!("{:?}", update);
98    ///     Ok(())
99    /// });
100    /// # }
101    /// ```
102    pub fn stream(&self) -> UpdatesStream {
103        UpdatesStream::new(self.clone())
104    }
105
106    /// Send a request to the Telegram server and do not wait for a response.
107    ///
108    /// # Examples
109    ///
110    /// ```rust
111    /// # extern crate futures;
112    /// # extern crate telegram_bot_fork;
113    /// # extern crate tokio;
114    /// # use futures::Future;
115    /// # use telegram_bot_fork::{Api, GetMe, ChatId};
116    /// # use telegram_bot_fork::prelude::*;
117    /// #
118    /// # fn main() {
119    /// # let telegram_token = "token";
120    /// # let api = Api::new(telegram_token).unwrap();
121    /// # if false {
122    /// let chat = ChatId::new(61031);
123    /// api.spawn(chat.text("Message"))
124    /// # }
125    /// # }
126    pub fn spawn<Req: Request>(&self, request: Req) {
127        tokio::executor::current_thread::spawn(self.send(request).then(|_| Ok(())));
128    }
129
130    /// Send a request to the Telegram server and wait for a response, timing out after `duration`.
131    /// Future will resolve to `None` if timeout fired.
132    ///
133    /// # Examples
134    ///
135    /// ```rust
136    /// # extern crate futures;
137    /// # extern crate telegram_bot_fork;
138    /// # extern crate tokio;
139    /// # use futures::Future;
140    /// # use telegram_bot_fork::{Api, GetMe};
141    /// #
142    /// # fn main() {
143    /// # let telegram_token = "token";
144    /// # let api = Api::new(telegram_token).unwrap();
145    /// # if false {
146    /// use std::time::Duration;
147    ///
148    /// let future = api.send_timeout(GetMe, Duration::from_secs(5));
149    /// future.and_then(|me| Ok(assert!(me.is_some())));
150    /// # }
151    /// # }
152    /// ```
153    pub fn send_timeout<Req: Request>(
154        &self,
155        request: Req,
156        duration: Duration,
157    ) -> TelegramFuture<Option<<Req::Response as ResponseType>::Type>> {
158        let timeout_future = tokio_timer::sleep(duration).from_err().map(|()| None);
159        let send_future = self.send(request).map(Some);
160
161        let future = timeout_future
162            .select(send_future)
163            .map(|(item, _next)| item)
164            .map_err(|(item, _next)| item);
165
166        TelegramFuture::new(Box::new(future))
167    }
168
169    /// Send a request to the Telegram server and wait for a response.
170    ///
171    /// # Examples
172    ///
173    /// ```rust
174    /// # extern crate futures;
175    /// # extern crate telegram_bot_fork;
176    /// # extern crate tokio;
177    /// # use futures::Future;
178    /// # use telegram_bot_fork::{Api, GetMe};
179    /// #
180    /// # fn main() {
181    /// # let telegram_token = "token";
182    /// # let api = Api::new(telegram_token).unwrap();
183    /// # if false {
184    /// let future = api.send(GetMe);
185    /// future.and_then(|me| Ok(println!("{:?}", me)));
186    /// # }
187    /// # }
188    /// ```
189    pub fn send<Req: Request>(
190        &self,
191        request: Req,
192    ) -> TelegramFuture<<Req::Response as ResponseType>::Type> {
193        let request = request.serialize().map_err(From::from);
194
195        let request = result(request);
196
197        let api = self.clone();
198        let response = request.and_then(move |request| {
199            let url = &api.url;
200            let token = &api.inner.token;
201            api.inner
202                .connector
203                .request(url.as_ref().map(String::as_str), token, request)
204        });
205
206        let future = response
207            .and_then(move |response| Req::Response::deserialize(response).map_err(From::from));
208
209        TelegramFuture::new(Box::new(future))
210    }
211}