1use super::{LocationDetails, User};
2use crate::client::Client;
3use serde::Deserialize;
4
5#[derive(Debug, Clone, Deserialize)]
6pub struct Attribute {
7 pub key: Option<String>,
8 pub key_label: Option<String>,
9 pub value: Option<String>,
10 pub value_label: Option<String>,
11 pub values: Option<Vec<String>>,
12 pub values_label: Option<Vec<String>>,
13 pub value_label_reader: Option<String>,
14 pub generic: Option<bool>,
15}
16
17#[derive(Debug, Clone, Deserialize)]
18pub struct Ad {
19 #[serde(rename = "list_id")]
20 pub id: Option<u64>,
21 pub first_publication_date: Option<String>,
22 pub expiration_date: Option<String>,
23 pub index_date: Option<String>,
24 pub status: Option<String>,
25 pub category_id: Option<String>,
26 pub category_name: Option<String>,
27 pub subject: Option<String>,
28 pub body: Option<String>,
29 pub brand: Option<String>,
30 pub ad_type: Option<String>,
31 pub url: Option<String>,
32 #[serde(rename = "price_cents")]
33 price_cents: Option<u64>,
34 pub images: Option<AdImages>,
35 pub attributes: Option<Vec<Attribute>>,
36 pub location: Option<LocationDetails>,
37 pub has_phone: Option<bool>,
38 pub counters: Option<AdCounters>,
39 pub owner: Option<AdOwner>,
40
41 #[serde(skip)]
42 client: Option<Client>,
43}
44
45#[derive(Debug, Clone, Deserialize)]
46pub struct AdImages {
47 pub urls_large: Option<Vec<String>>,
48 pub urls_thumb: Option<Vec<String>>,
49}
50
51#[derive(Debug, Clone, Deserialize)]
52pub struct AdCounters {
53 pub favorites: Option<u64>,
54}
55
56#[derive(Debug, Clone, Deserialize)]
57pub struct AdOwner {
58 pub user_id: Option<String>,
59}
60
61impl Ad {
62 pub fn price(&self) -> Option<f64> {
63 self.price_cents.map(|cents| cents as f64 / 100.0)
64 }
65
66 pub fn title(&self) -> Option<&str> {
67 self.subject.as_deref()
68 }
69
70 pub fn favorites(&self) -> Option<u64> {
71 self.counters.as_ref().and_then(|c| c.favorites)
72 }
73
74 pub fn user_id(&self) -> Option<&str> {
75 self.owner.as_ref().and_then(|o| o.user_id.as_deref())
76 }
77
78 pub fn image_urls(&self) -> Vec<&str> {
79 self.images
80 .as_ref()
81 .and_then(|img| img.urls_large.as_ref())
82 .map(|urls| urls.iter().map(|s| s.as_str()).collect())
83 .unwrap_or_default()
84 }
85
86 pub async fn get_user(&self) -> crate::Result<Option<User>> {
88 match (&self.client, self.user_id()) {
89 (Some(client), Some(user_id)) => Ok(Some(client.get_user(user_id).await?)),
90 _ => Ok(None),
91 }
92 }
93
94 pub(crate) fn with_client(mut self, client: Client) -> Self {
95 self.client = Some(client);
96 self
97 }
98}