mtgapi_client/api/card/
card_api.rs

1use crate::api::card::filter::CardFilter;
2use crate::api::card::filtertypes::CardResponseField;
3use crate::api::error::MtgApiErrorKind;
4use failure::Error;
5use failure::ResultExt;
6use reqwest::Client;
7
8use crate::api::response::ApiResponse;
9use crate::model::card::CardDetail;
10use std::rc::Weak;
11
12use crate::api::util;
13
14///Responsible for the calls to the /cards endpoint
15pub struct CardApi {
16    client: Weak<Client>,
17    url: String,
18}
19
20impl CardApi {
21    pub(crate) fn new(client: Weak<Client>, url: String) -> CardApi {
22        CardApi { client, url }
23    }
24
25    /// Returns a Request Object to fetch all cards
26    #[allow(dead_code)]
27    pub fn all(&self) -> Box<AllCardsRequest> {
28        AllCardsRequest::new(self.client.clone(), &self.url, 100)
29    }
30
31    /// Returns a Request Object to fetch all cards with a filter
32    #[allow(dead_code)]
33    pub fn all_filtered(&self, filter: CardFilter) -> Box<AllCardsRequest> {
34        AllCardsRequest::new_filtered(self.client.clone(), &self.url, 100, filter)
35    }
36
37    /// Returns a specific card by a specific id
38    pub async fn find(&self, id: u32) -> Result<ApiResponse<CardDetail>, Error> {
39        let url = [&self.url, "/cards/", &id.to_string()].join("");
40        let mut response = util::send_response(&url, &self.client).await?;
41        let headers = std::mem::take(response.headers_mut());
42        let body = response.text().await.context(MtgApiErrorKind::BodyReadError)?;
43        let card = util::retrieve_card_from_body(&body)?;
44        Ok(ApiResponse::new(*card, headers))
45    }
46}
47
48/// Request Object to be used to execute requests to the API
49#[allow(dead_code)]
50pub struct AllCardsRequest {
51    page: u32,
52    client: Weak<Client>,
53    url: String,
54    filter: CardFilter,
55    order_by: CardResponseField,
56    page_size: u32,
57}
58
59impl AllCardsRequest {
60    fn new(client: Weak<Client>, api_url: &str, page_size: u32) -> Box<AllCardsRequest> {
61        let url = [api_url, "cards"].join("/");
62        Box::new(AllCardsRequest {
63            page: 1,
64            client,
65            url,
66            filter: CardFilter(String::new()),
67            page_size,
68            order_by: CardResponseField::Name,
69        })
70    }
71
72    fn new_filtered(
73        client: Weak<Client>,
74        api_url: &str,
75        page_size: u32,
76        filter: CardFilter,
77    ) -> Box<AllCardsRequest> {
78        let url = [api_url, "cards"].join("/");
79        Box::new(AllCardsRequest {
80            page: 1,
81            client,
82            url,
83            filter,
84            page_size,
85            order_by: CardResponseField::Name,
86        })
87    }
88
89    /// Executes the call to the API.
90    /// Repeated calls to this method will return the different pages of the cards API
91
92    /// ```no_run
93    /// # use std::error::Error;
94    /// # use mtgapi_client::prelude::*;
95    /// # async fn get_some_cards() -> Result<(), Box<dyn Error>> {
96    /// let sdk = MtgClient::new(60);
97    /// let mut get_cards_request = sdk.cards().all();
98    /// let mut cards = Vec::new();
99    /// loop {
100    ///     let response = get_cards_request.next_page().await?;
101    ///     if response.content.is_empty() {break}
102    ///     cards.extend(response.content);
103    /// }
104    /// #
105    /// # Ok(())
106    /// # }
107    /// #
108    /// ```
109    /// # Errors
110    ///
111    /// If this function can't connect to the API or does not manage
112    /// to read the response, it will return an error.
113    ///
114    #[allow(dead_code)]
115    pub async fn next_page(&mut self) -> Result<ApiResponse<Vec<CardDetail>>, Error> {
116        let url = self.create_filtered_url();
117        let mut response = util::send_response(&url, &self.client).await?;
118        self.page += 1;
119        let headers = std::mem::take(response.headers_mut());
120        let body = response.text().await.context(MtgApiErrorKind::CardBodyParseError)?;
121        let cards = util::retrieve_cards_from_body(&body)?;
122        Ok(ApiResponse::new(cards, headers))
123    }
124
125    /// Sets the ordering of the cards
126    #[allow(dead_code)]
127    pub fn order_by(&mut self, field: CardResponseField) {
128        self.order_by = field;
129    }
130
131    /// Sets the page for the following API calls
132    #[allow(dead_code)]
133    pub fn set_page(&mut self, page: u32) {
134        self.page = page;
135    }
136
137    /// Sets the page size for the following API calls
138    #[allow(dead_code)]
139    pub fn set_page_size(&mut self, size: u32) {
140        self.page_size = size;
141    }
142
143    fn create_filtered_url(&self) -> String {
144        let page_filter = ["page", self.page.to_string().as_str()].join("=");
145        let paged_filter = if self.filter.0.is_empty() {
146            [self.filter.0.as_str(), &page_filter].join("")
147        } else {
148            [self.filter.0.as_str(), &page_filter].join("&")
149        };
150        let page_size_filter = ["pageSize", &self.page_size.to_string()].join("=");
151        let paged_filter_sized = [paged_filter, page_size_filter].join("&");
152
153        [self.url.as_str(), paged_filter_sized.as_str()].join("?")
154    }
155}