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}