vinted_rs/model/
item.rs

1use super::{photo::Photo, user::AdvancedUser};
2use crate::model::serde_config::bool_from_int_or_bool;
3use crate::model::{Deserialize, Serialize};
4#[cfg(feature = "redis")]
5use crate::model::{FromRedisValue, ToRedisArgs};
6use crate::utils::display_option;
7use std::fmt;
8
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Hash, Eq)]
10#[cfg_attr(feature = "redis", derive(FromRedisValue, ToRedisArgs,))]
11pub struct Item {
12    pub id: i64,
13    pub title: String,
14    pub size_title: String,
15    pub brand_title: String,
16    pub price: Price,
17    pub photo: Option<Photo>,
18    pub url: String,
19    pub is_visible: bool,
20    pub promoted: bool,
21    pub favourite_count: i32,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Hash, Eq)]
25pub struct Price {
26    pub amount: String,
27    pub currency_code: String,
28}
29
30impl fmt::Display for Item {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        writeln!(f, "ID: {}", self.id)?;
33        writeln!(f, "Title: {}", self.title)?;
34        writeln!(f, "Size Title: {}", self.size_title)?;
35        writeln!(f, "Brand Title: {}", self.brand_title)?;
36        writeln!(
37            f,
38            "Price: {} {}",
39            self.price.amount, self.price.currency_code
40        )?;
41        if let Some(ph) = &self.photo {
42            writeln!(f, "Photo: {}", ph)?;
43        }
44        writeln!(f, "URL: {}", self.url)?;
45        writeln!(f, "Is Visible: {}", self.is_visible)?;
46        writeln!(f, "Promoted: {}", self.promoted)?;
47        writeln!(f, "Favourite Count: {}", self.favourite_count)?;
48
49        Ok(())
50    }
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Hash, Eq)]
54#[cfg_attr(feature = "redis", derive(FromRedisValue, ToRedisArgs,))]
55pub struct AdvancedItem {
56    /// Vinted item ID
57    pub id: i64,
58    /// Item title
59    pub title: String,
60    /// Item description
61    pub description: String,
62    /// See [`Size`](crate::model::filter::size::Size)
63    #[serde(rename = "size")]
64    pub size_title: String,
65    /// See [`Brand`](crate::model::filter::brand::Brand)
66    #[serde(rename = "brand")]
67    pub brand_title: String,
68    #[serde(skip_serializing_if = "Option::is_none")]
69    pub composition: Option<String>,
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub extra_conditions: Option<String>,
72    /// See [`Brand`](crate::model::filter::brand::Brand)
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub brand_id: Option<i32>,
75    #[serde(skip_serializing_if = "Option::is_none")]
76    pub size_id: Option<i32>,
77    /// See [`ArticleStatus`](crate::model::filter::ArticleStatus)
78    #[serde(skip_serializing_if = "Option::is_none")]
79    pub status_id: Option<i32>,
80    /// Status of the item in French 🇫🇷
81    #[serde(rename = "status")]
82    #[serde(skip_serializing_if = "Option::is_none")]
83    pub status_fr: Option<String>,
84    #[serde(skip_serializing_if = "Option::is_none")]
85    pub disposal_conditions: Option<i32>,
86    #[serde(skip_serializing_if = "Option::is_none")]
87    pub catalog_id: Option<i32>,
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub color1_id: Option<i32>,
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub color1: Option<String>,
92    #[serde(skip_serializing_if = "Option::is_none")]
93    pub color2_id: Option<i32>,
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub color2: Option<String>,
96    pub package_size_id: i32,
97    /// See [`Country`](crate::model::filter::country::Country)
98    pub country_id: i32,
99    #[serde(skip_serializing_if = "Option::is_none")]
100    pub city_id: Option<i32>,
101    #[serde(skip_serializing_if = "Option::is_none")]
102    pub city: Option<String>,
103
104    //Stats
105    /// Number of bids on the item
106    pub active_bid_count: i32,
107    /// Number of times the item was added to favourites
108    pub favourite_count: i32,
109    /// Number of times the item was viewed
110    pub view_count: i32,
111    /// Moderation status of the item (Vinted internal use only)
112    pub moderation_status: i32,
113    #[serde(skip_serializing_if = "Option::is_none")]
114    pub last_push_up_at: Option<String>,
115    /// Related ['Brand'](crate::model::filter::brand::Brand) IDs
116    pub related_catalog_ids: Vec<i32>,
117
118    // Pricing
119    /// Original price of the item
120    pub original_price_numeric: String,
121    /// Currency the item was posted with. See [`Currency`](crate::model::filter::Currency) for valid currencies on Vinted
122    pub currency: String,
123    /// Current valid price of the item
124    pub price_numeric: String,
125
126    #[serde(skip_serializing_if = "Option::is_none")]
127    pub service_fee: Option<String>,
128
129    // Order by stats
130    pub created_at_ts: String,
131    #[serde(skip_serializing_if = "Option::is_none")]
132    pub updated_at_ts: Option<String>,
133    #[serde(skip_serializing_if = "Option::is_none")]
134    pub user_updated_at_ts: Option<String>,
135
136    // Assets
137    pub photos: Vec<Photo>,
138    pub url: String,
139    pub user: AdvancedUser,
140
141    // Some flags
142    #[serde(
143        skip_serializing_if = "Option::is_none",
144        deserialize_with = "bool_from_int_or_bool",
145        default
146    )]
147    pub is_for_sell: Option<bool>,
148    #[serde(
149        skip_serializing_if = "Option::is_none",
150        deserialize_with = "bool_from_int_or_bool",
151        default
152    )]
153    pub is_for_swap: Option<bool>,
154    #[serde(
155        skip_serializing_if = "Option::is_none",
156        deserialize_with = "bool_from_int_or_bool",
157        default
158    )]
159    pub is_for_give_away: Option<bool>,
160    #[serde(
161        skip_serializing_if = "Option::is_none",
162        deserialize_with = "bool_from_int_or_bool",
163        default
164    )]
165    pub is_handicraft: Option<bool>,
166    #[serde(
167        skip_serializing_if = "Option::is_none",
168        deserialize_with = "bool_from_int_or_bool",
169        default
170    )]
171    pub is_processing: Option<bool>,
172    #[serde(
173        skip_serializing_if = "Option::is_none",
174        deserialize_with = "bool_from_int_or_bool",
175        default
176    )]
177    pub is_draft: Option<bool>,
178    #[serde(
179        skip_serializing_if = "Option::is_none",
180        deserialize_with = "bool_from_int_or_bool",
181        default
182    )]
183    pub promoted: Option<bool>,
184    #[serde(
185        skip_serializing_if = "Option::is_none",
186        deserialize_with = "bool_from_int_or_bool",
187        default
188    )]
189    pub package_size_standard: Option<bool>,
190    #[serde(
191        skip_serializing_if = "Option::is_none",
192        deserialize_with = "bool_from_int_or_bool",
193        default
194    )]
195    pub related_catalogs_enabled: Option<bool>,
196    #[serde(
197        skip_serializing_if = "Option::is_none",
198        deserialize_with = "bool_from_int_or_bool",
199        default
200    )]
201    pub is_hidden: Option<bool>,
202    #[serde(
203        skip_serializing_if = "Option::is_none",
204        deserialize_with = "bool_from_int_or_bool",
205        default
206    )]
207    pub is_reserved: Option<bool>,
208    #[serde(skip_serializing_if = "Option::is_none")]
209    pub reserved_for_user_id: Option<i32>,
210    #[serde(
211        skip_serializing_if = "Option::is_none",
212        deserialize_with = "bool_from_int_or_bool",
213        default
214    )]
215    pub is_visible: Option<bool>,
216    #[serde(
217        skip_serializing_if = "Option::is_none",
218        deserialize_with = "bool_from_int_or_bool",
219        default
220    )]
221    pub is_visible_new: Option<bool>,
222    #[serde(
223        skip_serializing_if = "Option::is_none",
224        deserialize_with = "bool_from_int_or_bool",
225        default
226    )]
227    pub is_unisex: Option<bool>,
228
229    #[serde(
230        skip_serializing_if = "Option::is_none",
231        deserialize_with = "bool_from_int_or_bool",
232        default
233    )]
234    pub is_closed: Option<bool>,
235    #[serde(
236        skip_serializing_if = "Option::is_none",
237        deserialize_with = "bool_from_int_or_bool",
238        default
239    )]
240    pub is_closed_new: Option<bool>,
241    #[serde(
242        skip_serializing_if = "Option::is_none",
243        deserialize_with = "bool_from_int_or_bool",
244        default
245    )]
246    pub is_delayed_publication: Option<bool>,
247    #[serde(
248        skip_serializing_if = "Option::is_none",
249        deserialize_with = "bool_from_int_or_bool",
250        default
251    )]
252    pub can_be_sold: Option<bool>,
253}
254
255impl fmt::Display for AdvancedItem {
256    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257        writeln!(f, "ID: {}", self.id)?;
258        writeln!(f, "Title: {}", self.title)?;
259        writeln!(f, "Description: {}", self.description)?;
260        writeln!(
261            f,
262            "Size [Title: {}, ID: {:?}]",
263            self.size_title, self.size_id
264        )?;
265        writeln!(
266            f,
267            "Brand [ Title: {}, ID: {:?}]",
268            self.brand_title, self.brand_id
269        )?;
270        writeln!(f, "Composition: {:?}", self.composition)?;
271        writeln!(f, "Extra Conditions: {:?}", self.extra_conditions)?;
272        writeln!(f, "Status ID: {:?}", self.status_id)?;
273        writeln!(f, "Disposal Conditions: {:?}", self.disposal_conditions)?;
274        writeln!(f, "Catalog ID: {:?}", self.catalog_id)?;
275        writeln!(f, "Color1 ID: {:?}", self.color1_id)?;
276        writeln!(f, "Color2 ID: {:?}", self.color2_id)?;
277        writeln!(f, "Package Size ID: {}", self.package_size_id)?;
278        writeln!(f, "Country ID: {}", self.country_id)?;
279        writeln!(f, "City ID: {:?}", self.city_id)?;
280        writeln!(f, "City: {:?}", self.city)?;
281        writeln!(f, "Active Bid Count: {}", self.active_bid_count)?;
282        writeln!(f, "Favourite Count: {}", self.favourite_count)?;
283        writeln!(f, "View Count: {}", self.view_count)?;
284        writeln!(f, "Moderation Status: {}", self.moderation_status)?;
285        writeln!(f, "Related Catalog IDs: {:?}", self.related_catalog_ids)?;
286        writeln!(
287            f,
288            "Original Price: {} {}",
289            self.original_price_numeric, self.currency
290        )?;
291        writeln!(f, "Price: {} {}", self.price_numeric, self.currency)?;
292
293        writeln!(f, "\nFlags: {{")?;
294        writeln!(f, "  is_for_sell: {}", display_option(self.is_for_sell))?;
295        writeln!(f, "  is_for_swap: {}", display_option(self.is_for_swap))?;
296        writeln!(
297            f,
298            "  is_for_give_away: {}",
299            display_option(self.is_for_give_away)
300        )?;
301        writeln!(f, "  is_handicraft: {}", display_option(self.is_handicraft))?;
302        writeln!(f, "  is_processing: {}", display_option(self.is_processing))?;
303        writeln!(f, "  is_draft: {}", display_option(self.is_draft))?;
304        writeln!(f, "  promoted: {}", display_option(self.promoted))?;
305        writeln!(
306            f,
307            "  package_size_standard: {}",
308            display_option(self.package_size_standard)
309        )?;
310        writeln!(
311            f,
312            "  related_catalogs_enabled: {}",
313            display_option(self.related_catalogs_enabled)
314        )?;
315        writeln!(f, "  is_hidden: {}", display_option(self.is_hidden))?;
316        writeln!(f, "  is_reserved: {}", display_option(self.is_reserved))?;
317        writeln!(f, "  is_visible: {}", display_option(self.is_visible))?;
318        writeln!(f, "  is_unisex: {}", display_option(self.is_unisex))?;
319        // writeln!(f, "  is_closed: {}", display_option(self.is_closed))?;
320        writeln!(f, "}}\n")?;
321
322        for (num, photo) in self.photos.iter().enumerate() {
323            writeln!(f, "Pic {})", num)?;
324            writeln!(f, "{}", photo)?;
325        }
326
327        writeln!(f, "URL: {}\n", self.url)?;
328
329        writeln!(f, "@@@@@@@@@@@@@@@@@@@@@@@@@")?;
330        writeln!(f, "{}", self.user)?;
331        writeln!(f, "@@@@@@@@@@@@@@@@@@@@@@@@@")?;
332
333        Ok(())
334    }
335}