1use crate::client::BotClient;
2use crate::error::Result;
3use rustigram_types::message::{Message, ReplyParameters};
4use rustigram_types::payments::{LabeledPrice, ShippingOption, StarAmount, StarTransactions};
5use rustigram_types::suggested_post::SuggestedPostParameters;
6use rustigram_types::user::ChatId;
7use serde::Serialize;
8use std::future::{Future, IntoFuture};
9use std::pin::Pin;
10
11macro_rules! impl_into_future {
15 ($builder:ident, $return_ty:ty, $method:literal) => {
16 impl IntoFuture for $builder {
17 type Output = Result<$return_ty>;
18 type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
19
20 fn into_future(self) -> Self::IntoFuture {
21 Box::pin(async move { self.client.post_json($method, &self.params).await })
22 }
23 }
24 };
25}
26
27#[derive(Serialize)]
30struct SendInvoiceParams {
31 chat_id: ChatId,
32 title: String,
33 description: String,
34 payload: String,
35 currency: String,
36 prices: Vec<LabeledPrice>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 message_thread_id: Option<i64>,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 direct_messages_topic_id: Option<i64>,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 provider_token: Option<String>,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 max_tip_amount: Option<u32>,
45 #[serde(skip_serializing_if = "Option::is_none")]
46 suggested_tip_amounts: Option<Vec<u32>>,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 start_parameter: Option<String>,
49 #[serde(skip_serializing_if = "Option::is_none")]
50 provider_data: Option<String>,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 photo_url: Option<String>,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 photo_size: Option<u32>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 photo_width: Option<u32>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 photo_height: Option<u32>,
59 #[serde(skip_serializing_if = "Option::is_none")]
60 need_name: Option<bool>,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 need_phone_number: Option<bool>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 need_email: Option<bool>,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 need_shipping_address: Option<bool>,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 send_phone_number_to_provider: Option<bool>,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 send_email_to_provider: Option<bool>,
71 #[serde(skip_serializing_if = "Option::is_none")]
72 is_flexible: Option<bool>,
73 #[serde(skip_serializing_if = "Option::is_none")]
74 disable_notification: Option<bool>,
75 #[serde(skip_serializing_if = "Option::is_none")]
76 protect_content: Option<bool>,
77 #[serde(skip_serializing_if = "Option::is_none")]
78 allow_paid_broadcast: Option<bool>,
79 #[serde(skip_serializing_if = "Option::is_none")]
80 reply_parameters: Option<ReplyParameters>,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 reply_markup: Option<rustigram_types::keyboard::InlineKeyboardMarkup>,
83 #[serde(skip_serializing_if = "Option::is_none")]
84 suggested_post_parameters: Option<SuggestedPostParameters>,
85}
86
87pub struct SendInvoice {
89 client: BotClient,
90 params: SendInvoiceParams,
91}
92
93impl SendInvoice {
94 pub(crate) fn new(
95 client: BotClient,
96 chat_id: impl Into<ChatId>,
97 title: impl Into<String>,
98 description: impl Into<String>,
99 payload: impl Into<String>,
100 currency: impl Into<String>,
101 prices: Vec<LabeledPrice>,
102 ) -> Self {
103 Self {
104 client,
105 params: SendInvoiceParams {
106 chat_id: chat_id.into(),
107 title: title.into(),
108 description: description.into(),
109 payload: payload.into(),
110 currency: currency.into(),
111 prices,
112 message_thread_id: None,
113 direct_messages_topic_id: None,
114 provider_token: None,
115 max_tip_amount: None,
116 suggested_tip_amounts: None,
117 start_parameter: None,
118 provider_data: None,
119 photo_url: None,
120 photo_size: None,
121 photo_width: None,
122 photo_height: None,
123 need_name: None,
124 need_phone_number: None,
125 need_email: None,
126 need_shipping_address: None,
127 send_phone_number_to_provider: None,
128 send_email_to_provider: None,
129 is_flexible: None,
130 disable_notification: None,
131 protect_content: None,
132 allow_paid_broadcast: None,
133 reply_parameters: None,
134 reply_markup: None,
135 suggested_post_parameters: None,
136 },
137 }
138 }
139 pub fn message_thread_id(mut self, id: i64) -> Self {
141 self.params.message_thread_id = Some(id);
142 self
143 }
144 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
146 self.params.direct_messages_topic_id = Some(id);
147 self
148 }
149 pub fn provider_token(mut self, t: impl Into<String>) -> Self {
151 self.params.provider_token = Some(t.into());
152 self
153 }
154 pub fn need_name(mut self, v: bool) -> Self {
156 self.params.need_name = Some(v);
157 self
158 }
159 pub fn need_shipping_address(mut self, v: bool) -> Self {
161 self.params.need_shipping_address = Some(v);
162 self
163 }
164 pub fn is_flexible(mut self, v: bool) -> Self {
166 self.params.is_flexible = Some(v);
167 self
168 }
169 pub fn reply_markup(mut self, m: rustigram_types::keyboard::InlineKeyboardMarkup) -> Self {
171 self.params.reply_markup = Some(m);
172 self
173 }
174 pub fn suggested_post_parameters(mut self, params: SuggestedPostParameters) -> Self {
176 self.params.suggested_post_parameters = Some(params);
177 self
178 }
179}
180
181impl_into_future!(SendInvoice, Message, "sendInvoice");
182
183#[derive(Serialize)]
186struct CreateInvoiceLinkParams {
187 title: String,
188 description: String,
189 payload: String,
190 currency: String,
191 prices: Vec<LabeledPrice>,
192 #[serde(skip_serializing_if = "Option::is_none")]
193 business_connection_id: Option<String>,
194 #[serde(skip_serializing_if = "Option::is_none")]
195 provider_token: Option<String>,
196 #[serde(skip_serializing_if = "Option::is_none")]
197 subscription_period: Option<i64>,
198 #[serde(skip_serializing_if = "Option::is_none")]
199 max_tip_amount: Option<i64>,
200 #[serde(skip_serializing_if = "Option::is_none")]
201 suggested_tip_amounts: Option<Vec<i64>>,
202 #[serde(skip_serializing_if = "Option::is_none")]
203 provider_data: Option<String>,
204 #[serde(skip_serializing_if = "Option::is_none")]
205 photo_url: Option<String>,
206 #[serde(skip_serializing_if = "Option::is_none")]
207 photo_size: Option<i64>,
208 #[serde(skip_serializing_if = "Option::is_none")]
209 photo_width: Option<i64>,
210 #[serde(skip_serializing_if = "Option::is_none")]
211 photo_height: Option<i64>,
212 #[serde(skip_serializing_if = "Option::is_none")]
213 need_name: Option<bool>,
214 #[serde(skip_serializing_if = "Option::is_none")]
215 need_phone_number: Option<bool>,
216 #[serde(skip_serializing_if = "Option::is_none")]
217 need_email: Option<bool>,
218 #[serde(skip_serializing_if = "Option::is_none")]
219 need_shipping_address: Option<bool>,
220 #[serde(skip_serializing_if = "Option::is_none")]
221 send_phone_number_to_provider: Option<bool>,
222 #[serde(skip_serializing_if = "Option::is_none")]
223 send_email_to_provider: Option<bool>,
224 #[serde(skip_serializing_if = "Option::is_none")]
225 is_flexible: Option<bool>,
226}
227
228pub struct CreateInvoiceLink {
232 client: BotClient,
233 params: CreateInvoiceLinkParams,
234}
235
236impl CreateInvoiceLink {
237 pub(crate) fn new(
238 client: BotClient,
239 title: impl Into<String>,
240 description: impl Into<String>,
241 payload: impl Into<String>,
242 currency: impl Into<String>,
243 prices: Vec<LabeledPrice>,
244 ) -> Self {
245 Self {
246 client,
247 params: CreateInvoiceLinkParams {
248 title: title.into(),
249 description: description.into(),
250 payload: payload.into(),
251 currency: currency.into(),
252 prices,
253 business_connection_id: None,
254 provider_token: None,
255 subscription_period: None,
256 max_tip_amount: None,
257 suggested_tip_amounts: None,
258 provider_data: None,
259 photo_url: None,
260 photo_size: None,
261 photo_width: None,
262 photo_height: None,
263 need_name: None,
264 need_phone_number: None,
265 need_email: None,
266 need_shipping_address: None,
267 send_phone_number_to_provider: None,
268 send_email_to_provider: None,
269 is_flexible: None,
270 },
271 }
272 }
273 pub fn business_connection_id(mut self, id: impl Into<String>) -> Self {
275 self.params.business_connection_id = Some(id.into());
276 self
277 }
278 pub fn provider_token(mut self, t: impl Into<String>) -> Self {
280 self.params.provider_token = Some(t.into());
281 self
282 }
283 pub fn subscription_period(mut self, secs: i64) -> Self {
286 self.params.subscription_period = Some(secs);
287 self
288 }
289 pub fn max_tip_amount(mut self, v: i64) -> Self {
291 self.params.max_tip_amount = Some(v);
292 self
293 }
294 pub fn photo_url(mut self, url: impl Into<String>) -> Self {
296 self.params.photo_url = Some(url.into());
297 self
298 }
299 pub fn need_name(mut self, v: bool) -> Self {
301 self.params.need_name = Some(v);
302 self
303 }
304 pub fn need_phone_number(mut self, v: bool) -> Self {
306 self.params.need_phone_number = Some(v);
307 self
308 }
309 pub fn need_email(mut self, v: bool) -> Self {
311 self.params.need_email = Some(v);
312 self
313 }
314 pub fn need_shipping_address(mut self, v: bool) -> Self {
316 self.params.need_shipping_address = Some(v);
317 self
318 }
319 pub fn send_phone_number_to_provider(mut self, v: bool) -> Self {
321 self.params.send_phone_number_to_provider = Some(v);
322 self
323 }
324 pub fn send_email_to_provider(mut self, v: bool) -> Self {
326 self.params.send_email_to_provider = Some(v);
327 self
328 }
329 pub fn is_flexible(mut self, v: bool) -> Self {
331 self.params.is_flexible = Some(v);
332 self
333 }
334}
335
336impl_into_future!(CreateInvoiceLink, String, "createInvoiceLink");
337
338#[derive(Serialize)]
341struct AnswerShippingQueryParams {
342 shipping_query_id: String,
343 ok: bool,
344 #[serde(skip_serializing_if = "Option::is_none")]
345 shipping_options: Option<Vec<ShippingOption>>,
346 #[serde(skip_serializing_if = "Option::is_none")]
347 error_message: Option<String>,
348}
349
350pub struct AnswerShippingQuery {
355 client: BotClient,
356 params: AnswerShippingQueryParams,
357}
358
359impl AnswerShippingQuery {
360 pub(crate) fn new(client: BotClient, shipping_query_id: impl Into<String>, ok: bool) -> Self {
361 Self {
362 client,
363 params: AnswerShippingQueryParams {
364 shipping_query_id: shipping_query_id.into(),
365 ok,
366 shipping_options: None,
367 error_message: None,
368 },
369 }
370 }
371 pub fn shipping_options(mut self, opts: Vec<ShippingOption>) -> Self {
373 self.params.shipping_options = Some(opts);
374 self
375 }
376 pub fn error_message(mut self, msg: impl Into<String>) -> Self {
378 self.params.error_message = Some(msg.into());
379 self
380 }
381}
382
383impl_into_future!(AnswerShippingQuery, bool, "answerShippingQuery");
384
385#[derive(Serialize)]
388struct AnswerPreCheckoutQueryParams {
389 pre_checkout_query_id: String,
390 ok: bool,
391 #[serde(skip_serializing_if = "Option::is_none")]
392 error_message: Option<String>,
393}
394
395pub struct AnswerPreCheckoutQuery {
400 client: BotClient,
401 params: AnswerPreCheckoutQueryParams,
402}
403
404impl AnswerPreCheckoutQuery {
405 pub(crate) fn new(
406 client: BotClient,
407 pre_checkout_query_id: impl Into<String>,
408 ok: bool,
409 ) -> Self {
410 Self {
411 client,
412 params: AnswerPreCheckoutQueryParams {
413 pre_checkout_query_id: pre_checkout_query_id.into(),
414 ok,
415 error_message: None,
416 },
417 }
418 }
419 pub fn error_message(mut self, msg: impl Into<String>) -> Self {
422 self.params.error_message = Some(msg.into());
423 self
424 }
425}
426
427impl_into_future!(AnswerPreCheckoutQuery, bool, "answerPreCheckoutQuery");
428
429#[derive(Serialize)]
432struct RefundStarPaymentParams {
433 user_id: i64,
434 telegram_payment_charge_id: String,
435}
436
437pub struct RefundStarPayment {
441 client: BotClient,
442 params: RefundStarPaymentParams,
443}
444
445impl RefundStarPayment {
446 pub(crate) fn new(
447 client: BotClient,
448 user_id: i64,
449 telegram_payment_charge_id: impl Into<String>,
450 ) -> Self {
451 Self {
452 client,
453 params: RefundStarPaymentParams {
454 user_id,
455 telegram_payment_charge_id: telegram_payment_charge_id.into(),
456 },
457 }
458 }
459}
460
461impl_into_future!(RefundStarPayment, bool, "refundStarPayment");
462
463#[derive(Serialize)]
466struct EditUserStarSubscriptionParams {
467 user_id: i64,
468 telegram_payment_charge_id: String,
469 is_canceled: bool,
470}
471
472pub struct EditUserStarSubscription {
479 client: BotClient,
480 params: EditUserStarSubscriptionParams,
481}
482
483impl EditUserStarSubscription {
484 pub(crate) fn new(
485 client: BotClient,
486 user_id: i64,
487 telegram_payment_charge_id: impl Into<String>,
488 is_canceled: bool,
489 ) -> Self {
490 Self {
491 client,
492 params: EditUserStarSubscriptionParams {
493 user_id,
494 telegram_payment_charge_id: telegram_payment_charge_id.into(),
495 is_canceled,
496 },
497 }
498 }
499}
500
501impl_into_future!(EditUserStarSubscription, bool, "editUserStarSubscription");
502
503pub struct GetMyStarBalance {
507 client: BotClient,
508}
509
510impl GetMyStarBalance {
511 pub(crate) fn new(client: BotClient) -> Self {
512 Self { client }
513 }
514}
515
516impl IntoFuture for GetMyStarBalance {
517 type Output = Result<StarAmount>;
518 type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
519 fn into_future(self) -> Self::IntoFuture {
520 Box::pin(async move {
521 self.client
522 .post_json("getMyStarBalance", &serde_json::json!({}))
523 .await
524 })
525 }
526}
527
528#[derive(Serialize, Default)]
531struct GetStarTransactionsParams {
532 #[serde(skip_serializing_if = "Option::is_none")]
533 offset: Option<u32>,
534 #[serde(skip_serializing_if = "Option::is_none")]
535 limit: Option<u32>,
536}
537
538pub struct GetStarTransactions {
540 client: BotClient,
541 params: GetStarTransactionsParams,
542}
543
544impl GetStarTransactions {
545 pub(crate) fn new(client: BotClient) -> Self {
546 Self {
547 client,
548 params: Default::default(),
549 }
550 }
551 pub fn offset(mut self, v: u32) -> Self {
553 self.params.offset = Some(v);
554 self
555 }
556 pub fn limit(mut self, v: u32) -> Self {
558 self.params.limit = Some(v);
559 self
560 }
561}
562
563impl_into_future!(GetStarTransactions, StarTransactions, "getStarTransactions");