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 #[serde(skip_serializing_if = "Option::is_none")]
86 message_effect_id: Option<String>,
87}
88
89pub struct SendInvoice {
91 client: BotClient,
92 params: SendInvoiceParams,
93}
94
95impl SendInvoice {
96 pub(crate) fn new(
97 client: BotClient,
98 chat_id: impl Into<ChatId>,
99 title: impl Into<String>,
100 description: impl Into<String>,
101 payload: impl Into<String>,
102 currency: impl Into<String>,
103 prices: Vec<LabeledPrice>,
104 ) -> Self {
105 Self {
106 client,
107 params: SendInvoiceParams {
108 chat_id: chat_id.into(),
109 title: title.into(),
110 description: description.into(),
111 payload: payload.into(),
112 currency: currency.into(),
113 prices,
114 message_thread_id: None,
115 direct_messages_topic_id: None,
116 provider_token: None,
117 max_tip_amount: None,
118 suggested_tip_amounts: None,
119 start_parameter: None,
120 provider_data: None,
121 photo_url: None,
122 photo_size: None,
123 photo_width: None,
124 photo_height: None,
125 need_name: None,
126 need_phone_number: None,
127 need_email: None,
128 need_shipping_address: None,
129 send_phone_number_to_provider: None,
130 send_email_to_provider: None,
131 is_flexible: None,
132 disable_notification: None,
133 protect_content: None,
134 allow_paid_broadcast: None,
135 reply_parameters: None,
136 reply_markup: None,
137 suggested_post_parameters: None,
138 message_effect_id: None,
139 },
140 }
141 }
142 pub fn message_thread_id(mut self, id: i64) -> Self {
144 self.params.message_thread_id = Some(id);
145 self
146 }
147 pub fn direct_messages_topic_id(mut self, id: i64) -> Self {
149 self.params.direct_messages_topic_id = Some(id);
150 self
151 }
152 pub fn provider_token(mut self, t: impl Into<String>) -> Self {
154 self.params.provider_token = Some(t.into());
155 self
156 }
157 pub fn need_name(mut self, v: bool) -> Self {
159 self.params.need_name = Some(v);
160 self
161 }
162 pub fn need_shipping_address(mut self, v: bool) -> Self {
164 self.params.need_shipping_address = Some(v);
165 self
166 }
167 pub fn is_flexible(mut self, v: bool) -> Self {
169 self.params.is_flexible = Some(v);
170 self
171 }
172 pub fn reply_markup(mut self, m: rustigram_types::keyboard::InlineKeyboardMarkup) -> Self {
174 self.params.reply_markup = Some(m);
175 self
176 }
177 pub fn suggested_post_parameters(mut self, params: SuggestedPostParameters) -> Self {
179 self.params.suggested_post_parameters = Some(params);
180 self
181 }
182 pub fn message_effect_id(mut self, v: impl Into<String>) -> Self {
184 self.params.message_effect_id = Some(v.into());
185 self
186 }
187 pub fn max_tip_amount(mut self, v: u32) -> Self {
189 self.params.max_tip_amount = Some(v);
190 self
191 }
192 pub fn suggested_tip_amounts(mut self, v: Vec<u32>) -> Self {
194 self.params.suggested_tip_amounts = Some(v);
195 self
196 }
197 pub fn start_parameter(mut self, v: impl Into<String>) -> Self {
199 self.params.start_parameter = Some(v.into());
200 self
201 }
202 pub fn provider_data(mut self, v: impl Into<String>) -> Self {
204 self.params.provider_data = Some(v.into());
205 self
206 }
207 pub fn photo_url(mut self, v: impl Into<String>) -> Self {
209 self.params.photo_url = Some(v.into());
210 self
211 }
212 pub fn photo_size(mut self, v: u32) -> Self {
214 self.params.photo_size = Some(v);
215 self
216 }
217 pub fn photo_width(mut self, v: u32) -> Self {
219 self.params.photo_width = Some(v);
220 self
221 }
222 pub fn photo_height(mut self, v: u32) -> Self {
224 self.params.photo_height = Some(v);
225 self
226 }
227 pub fn need_phone_number(mut self, v: bool) -> Self {
229 self.params.need_phone_number = Some(v);
230 self
231 }
232 pub fn need_email(mut self, v: bool) -> Self {
234 self.params.need_email = Some(v);
235 self
236 }
237 pub fn send_phone_number_to_provider(mut self, v: bool) -> Self {
239 self.params.send_phone_number_to_provider = Some(v);
240 self
241 }
242 pub fn send_email_to_provider(mut self, v: bool) -> Self {
244 self.params.send_email_to_provider = Some(v);
245 self
246 }
247 pub fn disable_notification(mut self, v: bool) -> Self {
249 self.params.disable_notification = Some(v);
250 self
251 }
252 pub fn protect_content(mut self, v: bool) -> Self {
254 self.params.protect_content = Some(v);
255 self
256 }
257 pub fn allow_paid_broadcast(mut self, v: bool) -> Self {
259 self.params.allow_paid_broadcast = Some(v);
260 self
261 }
262 pub fn reply_parameters(mut self, v: ReplyParameters) -> Self {
264 self.params.reply_parameters = Some(v);
265 self
266 }
267}
268
269impl_into_future!(SendInvoice, Message, "sendInvoice");
270
271#[derive(Serialize)]
274struct CreateInvoiceLinkParams {
275 title: String,
276 description: String,
277 payload: String,
278 currency: String,
279 prices: Vec<LabeledPrice>,
280 #[serde(skip_serializing_if = "Option::is_none")]
281 business_connection_id: Option<String>,
282 #[serde(skip_serializing_if = "Option::is_none")]
283 provider_token: Option<String>,
284 #[serde(skip_serializing_if = "Option::is_none")]
285 subscription_period: Option<i64>,
286 #[serde(skip_serializing_if = "Option::is_none")]
287 max_tip_amount: Option<i64>,
288 #[serde(skip_serializing_if = "Option::is_none")]
289 suggested_tip_amounts: Option<Vec<i64>>,
290 #[serde(skip_serializing_if = "Option::is_none")]
291 provider_data: Option<String>,
292 #[serde(skip_serializing_if = "Option::is_none")]
293 photo_url: Option<String>,
294 #[serde(skip_serializing_if = "Option::is_none")]
295 photo_size: Option<i64>,
296 #[serde(skip_serializing_if = "Option::is_none")]
297 photo_width: Option<i64>,
298 #[serde(skip_serializing_if = "Option::is_none")]
299 photo_height: Option<i64>,
300 #[serde(skip_serializing_if = "Option::is_none")]
301 need_name: Option<bool>,
302 #[serde(skip_serializing_if = "Option::is_none")]
303 need_phone_number: Option<bool>,
304 #[serde(skip_serializing_if = "Option::is_none")]
305 need_email: Option<bool>,
306 #[serde(skip_serializing_if = "Option::is_none")]
307 need_shipping_address: Option<bool>,
308 #[serde(skip_serializing_if = "Option::is_none")]
309 send_phone_number_to_provider: Option<bool>,
310 #[serde(skip_serializing_if = "Option::is_none")]
311 send_email_to_provider: Option<bool>,
312 #[serde(skip_serializing_if = "Option::is_none")]
313 is_flexible: Option<bool>,
314}
315
316pub struct CreateInvoiceLink {
320 client: BotClient,
321 params: CreateInvoiceLinkParams,
322}
323
324impl CreateInvoiceLink {
325 pub(crate) fn new(
326 client: BotClient,
327 title: impl Into<String>,
328 description: impl Into<String>,
329 payload: impl Into<String>,
330 currency: impl Into<String>,
331 prices: Vec<LabeledPrice>,
332 ) -> Self {
333 Self {
334 client,
335 params: CreateInvoiceLinkParams {
336 title: title.into(),
337 description: description.into(),
338 payload: payload.into(),
339 currency: currency.into(),
340 prices,
341 business_connection_id: None,
342 provider_token: None,
343 subscription_period: None,
344 max_tip_amount: None,
345 suggested_tip_amounts: None,
346 provider_data: None,
347 photo_url: None,
348 photo_size: None,
349 photo_width: None,
350 photo_height: None,
351 need_name: None,
352 need_phone_number: None,
353 need_email: None,
354 need_shipping_address: None,
355 send_phone_number_to_provider: None,
356 send_email_to_provider: None,
357 is_flexible: None,
358 },
359 }
360 }
361 pub fn business_connection_id(mut self, id: impl Into<String>) -> Self {
363 self.params.business_connection_id = Some(id.into());
364 self
365 }
366 pub fn provider_token(mut self, t: impl Into<String>) -> Self {
368 self.params.provider_token = Some(t.into());
369 self
370 }
371 pub fn subscription_period(mut self, secs: i64) -> Self {
374 self.params.subscription_period = Some(secs);
375 self
376 }
377 pub fn max_tip_amount(mut self, v: i64) -> Self {
379 self.params.max_tip_amount = Some(v);
380 self
381 }
382 pub fn photo_url(mut self, url: impl Into<String>) -> Self {
384 self.params.photo_url = Some(url.into());
385 self
386 }
387 pub fn need_name(mut self, v: bool) -> Self {
389 self.params.need_name = Some(v);
390 self
391 }
392 pub fn need_phone_number(mut self, v: bool) -> Self {
394 self.params.need_phone_number = Some(v);
395 self
396 }
397 pub fn need_email(mut self, v: bool) -> Self {
399 self.params.need_email = Some(v);
400 self
401 }
402 pub fn need_shipping_address(mut self, v: bool) -> Self {
404 self.params.need_shipping_address = Some(v);
405 self
406 }
407 pub fn send_phone_number_to_provider(mut self, v: bool) -> Self {
409 self.params.send_phone_number_to_provider = Some(v);
410 self
411 }
412 pub fn send_email_to_provider(mut self, v: bool) -> Self {
414 self.params.send_email_to_provider = Some(v);
415 self
416 }
417 pub fn is_flexible(mut self, v: bool) -> Self {
419 self.params.is_flexible = Some(v);
420 self
421 }
422 pub fn suggested_tip_amounts(mut self, v: Vec<i64>) -> Self {
424 self.params.suggested_tip_amounts = Some(v);
425 self
426 }
427 pub fn provider_data(mut self, v: impl Into<String>) -> Self {
429 self.params.provider_data = Some(v.into());
430 self
431 }
432 pub fn photo_size(mut self, v: i64) -> Self {
434 self.params.photo_size = Some(v);
435 self
436 }
437 pub fn photo_width(mut self, v: i64) -> Self {
439 self.params.photo_width = Some(v);
440 self
441 }
442 pub fn photo_height(mut self, v: i64) -> Self {
444 self.params.photo_height = Some(v);
445 self
446 }
447}
448
449impl_into_future!(CreateInvoiceLink, String, "createInvoiceLink");
450
451#[derive(Serialize)]
454struct AnswerShippingQueryParams {
455 shipping_query_id: String,
456 ok: bool,
457 #[serde(skip_serializing_if = "Option::is_none")]
458 shipping_options: Option<Vec<ShippingOption>>,
459 #[serde(skip_serializing_if = "Option::is_none")]
460 error_message: Option<String>,
461}
462
463pub struct AnswerShippingQuery {
468 client: BotClient,
469 params: AnswerShippingQueryParams,
470}
471
472impl AnswerShippingQuery {
473 pub(crate) fn new(client: BotClient, shipping_query_id: impl Into<String>, ok: bool) -> Self {
474 Self {
475 client,
476 params: AnswerShippingQueryParams {
477 shipping_query_id: shipping_query_id.into(),
478 ok,
479 shipping_options: None,
480 error_message: None,
481 },
482 }
483 }
484 pub fn shipping_options(mut self, opts: Vec<ShippingOption>) -> Self {
486 self.params.shipping_options = Some(opts);
487 self
488 }
489 pub fn error_message(mut self, msg: impl Into<String>) -> Self {
491 self.params.error_message = Some(msg.into());
492 self
493 }
494}
495
496impl_into_future!(AnswerShippingQuery, bool, "answerShippingQuery");
497
498#[derive(Serialize)]
501struct AnswerPreCheckoutQueryParams {
502 pre_checkout_query_id: String,
503 ok: bool,
504 #[serde(skip_serializing_if = "Option::is_none")]
505 error_message: Option<String>,
506}
507
508pub struct AnswerPreCheckoutQuery {
513 client: BotClient,
514 params: AnswerPreCheckoutQueryParams,
515}
516
517impl AnswerPreCheckoutQuery {
518 pub(crate) fn new(
519 client: BotClient,
520 pre_checkout_query_id: impl Into<String>,
521 ok: bool,
522 ) -> Self {
523 Self {
524 client,
525 params: AnswerPreCheckoutQueryParams {
526 pre_checkout_query_id: pre_checkout_query_id.into(),
527 ok,
528 error_message: None,
529 },
530 }
531 }
532 pub fn error_message(mut self, msg: impl Into<String>) -> Self {
535 self.params.error_message = Some(msg.into());
536 self
537 }
538}
539
540impl_into_future!(AnswerPreCheckoutQuery, bool, "answerPreCheckoutQuery");
541
542#[derive(Serialize)]
545struct RefundStarPaymentParams {
546 user_id: i64,
547 telegram_payment_charge_id: String,
548}
549
550pub struct RefundStarPayment {
554 client: BotClient,
555 params: RefundStarPaymentParams,
556}
557
558impl RefundStarPayment {
559 pub(crate) fn new(
560 client: BotClient,
561 user_id: i64,
562 telegram_payment_charge_id: impl Into<String>,
563 ) -> Self {
564 Self {
565 client,
566 params: RefundStarPaymentParams {
567 user_id,
568 telegram_payment_charge_id: telegram_payment_charge_id.into(),
569 },
570 }
571 }
572}
573
574impl_into_future!(RefundStarPayment, bool, "refundStarPayment");
575
576#[derive(Serialize)]
579struct EditUserStarSubscriptionParams {
580 user_id: i64,
581 telegram_payment_charge_id: String,
582 is_canceled: bool,
583}
584
585pub struct EditUserStarSubscription {
592 client: BotClient,
593 params: EditUserStarSubscriptionParams,
594}
595
596impl EditUserStarSubscription {
597 pub(crate) fn new(
598 client: BotClient,
599 user_id: i64,
600 telegram_payment_charge_id: impl Into<String>,
601 is_canceled: bool,
602 ) -> Self {
603 Self {
604 client,
605 params: EditUserStarSubscriptionParams {
606 user_id,
607 telegram_payment_charge_id: telegram_payment_charge_id.into(),
608 is_canceled,
609 },
610 }
611 }
612}
613
614impl_into_future!(EditUserStarSubscription, bool, "editUserStarSubscription");
615
616pub struct GetMyStarBalance {
620 client: BotClient,
621}
622
623impl GetMyStarBalance {
624 pub(crate) fn new(client: BotClient) -> Self {
625 Self { client }
626 }
627}
628
629impl IntoFuture for GetMyStarBalance {
630 type Output = Result<StarAmount>;
631 type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
632 fn into_future(self) -> Self::IntoFuture {
633 Box::pin(async move {
634 self.client
635 .post_json("getMyStarBalance", &serde_json::json!({}))
636 .await
637 })
638 }
639}
640
641#[derive(Serialize, Default)]
644struct GetStarTransactionsParams {
645 #[serde(skip_serializing_if = "Option::is_none")]
646 offset: Option<u32>,
647 #[serde(skip_serializing_if = "Option::is_none")]
648 limit: Option<u32>,
649}
650
651pub struct GetStarTransactions {
653 client: BotClient,
654 params: GetStarTransactionsParams,
655}
656
657impl GetStarTransactions {
658 pub(crate) fn new(client: BotClient) -> Self {
659 Self {
660 client,
661 params: Default::default(),
662 }
663 }
664 pub fn offset(mut self, v: u32) -> Self {
666 self.params.offset = Some(v);
667 self
668 }
669 pub fn limit(mut self, v: u32) -> Self {
671 self.params.limit = Some(v);
672 self
673 }
674}
675
676impl_into_future!(GetStarTransactions, StarTransactions, "getStarTransactions");