tgbot/types/definitions/payment/
shipping.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{
4    api::{Method, Payload},
5    types::{LabeledPrice, User},
6};
7
8/// Represents a shipping address.
9#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
10pub struct ShippingAddress {
11    /// City.
12    pub city: String,
13    /// ISO 3166-1 alpha-2 country code.
14    pub country_code: String,
15    /// Address post code.
16    pub post_code: String,
17    /// State, if applicable.
18    pub state: String,
19    /// First line for the address.
20    pub street_line1: String,
21    /// Second line for the address.
22    pub street_line2: String,
23}
24
25impl ShippingAddress {
26    /// Creates a new `ShippingAddress`.
27    ///
28    /// # Arguments
29    ///
30    /// * `city` - City.
31    /// * `country_code` - ISO 3166-1 alpha-2 country code.
32    /// * `post_code` - Post code.
33    /// * `state` - State.
34    /// * `street_line1` - First line for the address.
35    /// * `street_line2` - Second line for the address.
36    pub fn new<A, B, C, D, E, F>(
37        city: A,
38        country_code: B,
39        post_code: C,
40        state: D,
41        street_line1: E,
42        street_line2: F,
43    ) -> Self
44    where
45        A: Into<String>,
46        B: Into<String>,
47        C: Into<String>,
48        D: Into<String>,
49        E: Into<String>,
50        F: Into<String>,
51    {
52        Self {
53            city: city.into(),
54            country_code: country_code.into(),
55            post_code: post_code.into(),
56            state: state.into(),
57            street_line1: street_line1.into(),
58            street_line2: street_line2.into(),
59        }
60    }
61}
62
63/// Represents a shipping option.
64#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
65pub struct ShippingOption {
66    id: String,
67    title: String,
68    prices: Vec<LabeledPrice>,
69}
70
71impl ShippingOption {
72    /// Creates a new `ShippingOption`.
73    ///
74    /// # Arguments
75    ///
76    /// * `id` - Shipping option identifier.
77    /// * `title` - Option title.
78    /// * `prices` - List of price portions.
79    pub fn new<A, B, C>(id: A, title: B, prices: C) -> Self
80    where
81        A: Into<String>,
82        B: Into<String>,
83        C: IntoIterator<Item = LabeledPrice>,
84    {
85        Self {
86            id: id.into(),
87            title: title.into(),
88            prices: prices.into_iter().collect(),
89        }
90    }
91
92    /// Returns the ID of the option.
93    pub fn id(&self) -> &str {
94        &self.id
95    }
96
97    /// Returns the title of the option.
98    pub fn title(&self) -> &str {
99        &self.title
100    }
101
102    /// Returns the list of price portions.
103    pub fn prices(&self) -> &[LabeledPrice] {
104        &self.prices
105    }
106}
107
108/// Represents a shipping query.
109#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
110pub struct ShippingQuery {
111    /// Unique query identifier.
112    pub id: String,
113    /// User who sent the query.
114    pub from: User,
115    /// Bot specified invoice payload.
116    pub invoice_payload: String,
117    /// User specified shipping address.
118    pub shipping_address: ShippingAddress,
119}
120
121impl ShippingQuery {
122    /// Creates a new `ShippingQuery`.
123    ///
124    /// # Arguments
125    ///
126    /// * `id` - Query ID.
127    /// * `from` - Query sender.
128    /// * `invoice_payload` - Bot specified payload.
129    /// * `shipping_address` - User specified address.
130    pub fn new<A, B>(id: A, from: User, invoice_payload: B, shipping_address: ShippingAddress) -> Self
131    where
132        A: Into<String>,
133        B: Into<String>,
134    {
135        Self {
136            id: id.into(),
137            from,
138            invoice_payload: invoice_payload.into(),
139            shipping_address,
140        }
141    }
142}
143
144/// Replies to a shipping query.
145///
146/// If you sent an invoice requesting a shipping address
147/// and the parameter `is_flexible` was specified,
148/// the Bot API will send an [`crate::types::UpdateType::ShippingQuery`] to the bot.
149#[serde_with::skip_serializing_none]
150#[derive(Clone, Debug, Serialize)]
151pub struct AnswerShippingQuery {
152    ok: bool,
153    shipping_query_id: String,
154    error_message: Option<String>,
155    shipping_options: Option<Vec<ShippingOption>>,
156}
157
158impl AnswerShippingQuery {
159    /// Creates a new `AnswerShippingQuery` with a success answer.
160    ///
161    /// # Arguments
162    ///
163    /// * `id` - Unique identifier of the query to be answered.
164    /// * `options` - Array of available shipping options.
165    pub fn ok<A, B>(id: A, options: B) -> Self
166    where
167        A: Into<String>,
168        B: IntoIterator<Item = ShippingOption>,
169    {
170        Self {
171            ok: true,
172            shipping_query_id: id.into(),
173            error_message: None,
174            shipping_options: Some(options.into_iter().collect()),
175        }
176    }
177
178    /// Creates a new `AnswerShippingQuery` with an error answer.
179    ///
180    /// # Arguments
181    ///
182    /// * `id` - Unique identifier of the query to be answered.
183    /// * `message` - Error message in human readable form.
184    pub fn error<A, B>(id: A, message: B) -> Self
185    where
186        A: Into<String>,
187        B: Into<String>,
188    {
189        Self {
190            ok: false,
191            shipping_query_id: id.into(),
192            error_message: Some(message.into()),
193            shipping_options: None,
194        }
195    }
196}
197
198impl Method for AnswerShippingQuery {
199    type Response = bool;
200
201    fn into_payload(self) -> Payload {
202        Payload::json("answerShippingQuery", self)
203    }
204}