tmdb_api/changes/
list.rs

1use chrono::NaiveDate;
2
3use crate::client::Executor;
4
5const TV_PATH: &str = "/tv/changes";
6const MOVIE_PATH: &str = "/movie/changes";
7const PERSON_PATH: &str = "/person/changes";
8
9#[derive(Clone, Debug, Default, Serialize)]
10pub struct Params {
11    /// Filter the results with a start date.
12    #[serde(skip_serializing_if = "Option::is_none")]
13    pub start_date: Option<NaiveDate>,
14    /// Filter the results with an end date.
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub end_date: Option<NaiveDate>,
17    /// Which page to query.
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub page: Option<u32>,
20}
21
22impl Params {
23    pub fn set_start_date(&mut self, value: NaiveDate) {
24        self.start_date = Some(value);
25    }
26
27    pub fn with_start_date(mut self, value: NaiveDate) -> Self {
28        self.set_start_date(value);
29        self
30    }
31
32    pub fn set_end_date(&mut self, value: NaiveDate) {
33        self.end_date = Some(value);
34    }
35
36    pub fn with_end_date(mut self, value: NaiveDate) -> Self {
37        self.set_end_date(value);
38        self
39    }
40
41    pub fn set_page(&mut self, value: u32) {
42        self.page = Some(value);
43    }
44
45    pub fn with_page(mut self, value: u32) -> Self {
46        self.set_page(value);
47        self
48    }
49}
50
51impl<E: Executor> crate::Client<E> {
52    /// Get a list of all of the movie ids that have been changed in the past 24 hours.
53    ///
54    /// ```rust
55    /// use tmdb_api::Client;
56    /// use tmdb_api::client::reqwest::ReqwestExecutor;
57    ///
58    /// #[tokio::main]
59    /// async fn main() {
60    ///     let client = Client::<ReqwestExecutor>::new("this-is-my-secret-token".into());
61    ///     match client.list_movie_changes(&Default::default()).await {
62    ///         Ok(res) => println!("found: {:#?}", res),
63    ///         Err(err) => eprintln!("error: {:?}", err),
64    ///     };
65    /// }
66    /// ```
67    pub async fn list_movie_changes(
68        &self,
69        params: &Params,
70    ) -> crate::Result<crate::common::PaginatedResult<super::Change>> {
71        self.execute(MOVIE_PATH, params).await
72    }
73
74    /// Get a list of all of the person ids that have been changed in the past 24 hours.
75    ///
76    /// ```rust
77    /// use tmdb_api::Client;
78    /// use tmdb_api::client::reqwest::ReqwestExecutor;
79    ///
80    /// #[tokio::main]
81    /// async fn main() {
82    ///     let client = Client::<ReqwestExecutor>::new("this-is-my-secret-token".into());
83    ///     match client.list_person_changes(&Default::default()).await {
84    ///         Ok(res) => println!("found: {:#?}", res),
85    ///         Err(err) => eprintln!("error: {:?}", err),
86    ///     };
87    /// }
88    /// ```
89    pub async fn list_person_changes(
90        &self,
91        params: &Params,
92    ) -> crate::Result<crate::common::PaginatedResult<super::Change>> {
93        self.execute(PERSON_PATH, params).await
94    }
95
96    /// Get a list of all of the tvshow ids that have been changed in the past 24 hours.
97    ///
98    /// ```rust
99    /// use tmdb_api::Client;
100    /// use tmdb_api::client::reqwest::ReqwestExecutor;
101    ///
102    /// #[tokio::main]
103    /// async fn main() {
104    ///     let client = Client::<ReqwestExecutor>::new("this-is-my-secret-token".into());
105    ///     match client.list_tvshow_changes(&Default::default()).await {
106    ///         Ok(res) => println!("found: {:#?}", res),
107    ///         Err(err) => eprintln!("error: {:?}", err),
108    ///     };
109    /// }
110    /// ```
111    pub async fn list_tvshow_changes(
112        &self,
113        params: &Params,
114    ) -> crate::Result<crate::common::PaginatedResult<super::Change>> {
115        self.execute(TV_PATH, params).await
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    use crate::changes::list::Params;
122    use crate::client::Client;
123    use crate::client::reqwest::ReqwestExecutor;
124    use chrono::NaiveDate;
125    use mockito::Matcher;
126
127    #[tokio::test]
128    async fn tv_works() {
129        let mut server = mockito::Server::new_async().await;
130        let m = server
131            .mock("GET", super::TV_PATH)
132            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
133            .with_status(200)
134            .with_header("content-type", "application/json")
135            .with_body(include_str!("../../assets/tv-all-changes.json"))
136            .create_async()
137            .await;
138
139        let client = Client::<ReqwestExecutor>::builder()
140            .with_api_key("secret".into())
141            .with_base_url(server.url())
142            .build()
143            .unwrap();
144        let result = client
145            .list_tvshow_changes(&Default::default())
146            .await
147            .unwrap();
148        assert_eq!(result.page, 1);
149
150        m.assert_async().await;
151    }
152
153    #[tokio::test]
154    async fn tv_works_with_args() {
155        let mut server = mockito::Server::new_async().await;
156        let m = server
157            .mock("GET", super::TV_PATH)
158            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
159            .match_query(Matcher::AllOf(vec![
160                Matcher::UrlEncoded("api_key".into(), "secret".into()),
161                Matcher::UrlEncoded("start_date".into(), "2015-03-14".into()),
162                Matcher::UrlEncoded("end_date".into(), "2019-03-14".into()),
163                Matcher::UrlEncoded("page".into(), "2".into()),
164            ]))
165            .with_status(200)
166            .with_header("content-type", "application/json")
167            .with_body(include_str!("../../assets/tv-all-changes.json"))
168            .create_async()
169            .await;
170
171        let client = Client::<ReqwestExecutor>::builder()
172            .with_api_key("secret".into())
173            .with_base_url(server.url())
174            .build()
175            .unwrap();
176        let result = client
177            .list_tvshow_changes(
178                &Params::default()
179                    .with_start_date(NaiveDate::from_ymd_opt(2015, 3, 14).unwrap())
180                    .with_end_date(NaiveDate::from_ymd_opt(2019, 3, 14).unwrap())
181                    .with_page(2),
182            )
183            .await
184            .unwrap();
185        assert_eq!(result.page, 1);
186        m.assert_async().await;
187    }
188
189    #[tokio::test]
190    async fn movie_works() {
191        let mut server = mockito::Server::new_async().await;
192        let m = server
193            .mock("GET", super::MOVIE_PATH)
194            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
195            .with_status(200)
196            .with_header("content-type", "application/json")
197            .with_body(include_str!("../../assets/movie-all-changes.json"))
198            .create_async()
199            .await;
200
201        let client = Client::<ReqwestExecutor>::builder()
202            .with_api_key("secret".into())
203            .with_base_url(server.url())
204            .build()
205            .unwrap();
206        let result = client
207            .list_movie_changes(&Default::default())
208            .await
209            .unwrap();
210        assert_eq!(result.page, 1);
211
212        m.assert_async().await;
213    }
214
215    #[tokio::test]
216    async fn person_works() {
217        let mut server = mockito::Server::new_async().await;
218        let m = server
219            .mock("GET", super::PERSON_PATH)
220            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
221            .with_status(200)
222            .with_header("content-type", "application/json")
223            .with_body(include_str!("../../assets/movie-all-changes.json"))
224            .create_async()
225            .await;
226
227        let client = Client::<ReqwestExecutor>::builder()
228            .with_api_key("secret".into())
229            .with_base_url(server.url())
230            .build()
231            .unwrap();
232        let result = client
233            .list_person_changes(&Default::default())
234            .await
235            .unwrap();
236        assert_eq!(result.page, 1);
237
238        m.assert_async().await;
239    }
240
241    #[tokio::test]
242    async fn invalid_api_key() {
243        let mut server = mockito::Server::new_async().await;
244        let m = server
245            .mock("GET", super::TV_PATH)
246            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
247            .with_status(401)
248            .with_header("content-type", "application/json")
249            .with_body(include_str!("../../assets/invalid-api-key.json"))
250            .create_async()
251            .await;
252
253        let client = Client::<ReqwestExecutor>::builder()
254            .with_api_key("secret".into())
255            .with_base_url(server.url())
256            .build()
257            .unwrap();
258        let err = client
259            .list_tvshow_changes(&Default::default())
260            .await
261            .unwrap_err();
262        let server_err = err.as_server_error().unwrap();
263        assert_eq!(server_err.status_code, 7);
264
265        m.assert_async().await;
266    }
267
268    #[tokio::test]
269    async fn resource_not_found() {
270        let mut server = mockito::Server::new_async().await;
271        let m = server
272            .mock("GET", super::TV_PATH)
273            .match_query(Matcher::UrlEncoded("api_key".into(), "secret".into()))
274            .with_status(404)
275            .with_header("content-type", "application/json")
276            .with_body(include_str!("../../assets/resource-not-found.json"))
277            .create_async()
278            .await;
279
280        let client = Client::<ReqwestExecutor>::builder()
281            .with_api_key("secret".into())
282            .with_base_url(server.url())
283            .build()
284            .unwrap();
285        let err = client
286            .list_tvshow_changes(&Default::default())
287            .await
288            .unwrap_err();
289        let server_err = err.as_server_error().unwrap();
290        assert_eq!(server_err.status_code, 34);
291
292        m.assert_async().await;
293    }
294}
295
296#[cfg(all(test, feature = "integration"))]
297mod integration_tests {
298    use crate::client::Client;
299    use crate::client::reqwest::ReqwestExecutor;
300
301    #[tokio::test]
302    async fn execute_tv() {
303        let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
304        let client = Client::<ReqwestExecutor>::new(secret);
305
306        let result = client
307            .list_tvshow_changes(&Default::default())
308            .await
309            .unwrap();
310        assert_eq!(result.page, 1);
311    }
312
313    #[tokio::test]
314    async fn execute_movie() {
315        let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
316        let client = Client::<ReqwestExecutor>::new(secret);
317
318        let result = client
319            .list_movie_changes(&Default::default())
320            .await
321            .unwrap();
322        assert_eq!(result.page, 1);
323    }
324
325    #[tokio::test]
326    async fn execute_person() {
327        let secret = std::env::var("TMDB_TOKEN_V3").unwrap();
328        let client = Client::<ReqwestExecutor>::new(secret);
329
330        let result = client
331            .list_person_changes(&Default::default())
332            .await
333            .unwrap();
334        assert_eq!(result.page, 1);
335    }
336}