pexels_api/collections/
media.rs

1use crate::{
2    MediaResponse, MediaSort, MediaType as LibType, Pexels, PexelsError, PEXELS_API,
3    PEXELS_COLLECTIONS_PATH, PEXELS_VERSION,
4};
5use url::Url;
6
7/// Represents a request to fetch a specific media item by its ID from the Pexels API.
8/// This endpoint returns all media items (photos and videos) within a single collection.
9/// Use the `type` parameter to filter results to only photos or only videos.
10pub struct Media {
11    id: String,
12    r#type: Option<LibType>,
13    sort: Option<MediaSort>,
14    page: Option<usize>,
15    per_page: Option<usize>,
16}
17
18impl Media {
19    /// Creates a new `MediaBuilder` for constructing a `Media` request.
20    pub fn builder() -> MediaBuilder {
21        MediaBuilder::new()
22    }
23
24    /// Constructs the URI for the media request based on the builder's parameters.
25    pub fn create_uri(&self) -> crate::BuilderResult {
26        let uri =
27            format!("{}/{}/{}/{}", PEXELS_API, PEXELS_VERSION, PEXELS_COLLECTIONS_PATH, self.id);
28
29        let mut url = Url::parse(uri.as_str())?;
30
31        if let Some(r#type) = &self.r#type {
32            match r#type {
33                LibType::Empty => {}
34                _ => {
35                    url.query_pairs_mut().append_pair("type", r#type.as_str());
36                }
37            }
38        }
39
40        if let Some(sort) = &self.sort {
41            url.query_pairs_mut().append_pair("sort", sort.as_str());
42        }
43
44        if let Some(page) = &self.page {
45            url.query_pairs_mut().append_pair("page", page.to_string().as_str());
46        }
47
48        if let Some(per_page) = &self.per_page {
49            url.query_pairs_mut().append_pair("per_page", per_page.to_string().as_str());
50        }
51
52        Ok(url.into())
53    }
54
55    /// Fetches the media data from the Pexels API.
56    pub async fn fetch(&self, client: &Pexels) -> Result<MediaResponse, PexelsError> {
57        let url = self.create_uri()?;
58        let response = client.make_request(url.as_str()).await?;
59        let media_response: MediaResponse = serde_json::from_value(response)?;
60        Ok(media_response)
61    }
62}
63
64/// Builder for constructing a `Media` request.
65#[derive(Default)]
66pub struct MediaBuilder {
67    id: String,
68    r#type: Option<LibType>,
69    sort: Option<MediaSort>,
70    page: Option<usize>,
71    per_page: Option<usize>,
72}
73
74impl MediaBuilder {
75    /// Creates a new `MediaBuilder`.
76    pub fn new() -> Self {
77        Self { id: "".to_string(), r#type: None, sort: None, page: None, per_page: None }
78    }
79
80    /// Sets the ID of the media item to be fetched.
81    pub fn id(mut self, id: String) -> Self {
82        self.id = id;
83        self
84    }
85
86    /// Sets the type of media to be fetched (photo or video).
87    pub fn r#type(mut self, r#type: LibType) -> Self {
88        self.r#type = Some(r#type);
89        self
90    }
91
92    /// Sets the sorting order of the media items.
93    pub fn sort(mut self, sort: MediaSort) -> Self {
94        self.sort = Some(sort);
95        self
96    }
97
98    /// Sets the page number for the request.
99    pub fn page(mut self, page: usize) -> Self {
100        self.page = Some(page);
101        self
102    }
103
104    /// Sets the number of results per page for the request.
105    pub fn per_page(mut self, per_page: usize) -> Self {
106        self.per_page = Some(per_page);
107        self
108    }
109
110    /// Builds a `Media` instance from the `MediaBuilder`.
111    pub fn build(self) -> Media {
112        Media {
113            id: self.id,
114            r#type: self.r#type,
115            sort: self.sort,
116            page: self.page,
117            per_page: self.per_page,
118        }
119    }
120}
121
122#[cfg(test)]
123mod tests {
124    use super::*;
125
126    #[test]
127    fn test_id() {
128        let uri = MediaBuilder::new().id("123".to_string()).build();
129        assert_eq!("https://api.pexels.com/v1/collections/123", uri.create_uri().unwrap());
130    }
131}