1use core::ops::Deref;
4use core::time::Duration;
5use std::sync::RwLock;
6
7use governor::Jitter;
8use reqwest::Request;
9use reqwest::header;
10use serde::de::DeserializeOwned;
11
12use crate::{Cache, CachePolicy, Config};
13
14pub mod collections;
15pub mod episodes;
16pub mod movies;
17pub mod seasons;
18pub mod shows;
19
20#[derive(Debug, thiserror::Error)]
22pub enum Error {
23 #[error("url parse error: {0}")]
25 Url(#[from] url::ParseError),
26 #[error("reqwest error: {0}")]
28 Reqwest(#[from] reqwest::Error),
29 #[error("json error: {0}")]
31 Json(#[from] serde_json::Error),
32}
33
34fn make_request(config: &Config, path: &str, language: Option<&str>) -> Result<Request, Error> {
35 let url = config.base_url.join(path)?;
36
37 let mut builder = config.client.get(url).header(
38 header::AUTHORIZATION,
39 format!("Bearer {}", config.bearer_token),
40 );
41 if let Some(ref user_agent) = config.user_agent {
42 builder = builder.header(header::USER_AGENT, user_agent);
43 }
44 if let Some(language) = language {
45 builder = builder.query(&[("language", language)]);
46 }
47
48 Ok(builder.build()?)
49}
50
51async fn exec_request<T: DeserializeOwned>(
52 config: &Config,
53 cache: &dyn Cache,
54 policy: &RwLock<CachePolicy>,
55 request: Request,
56) -> Result<T, Error> {
57 let (read_cache, write_cache) = if let Ok(guard) = policy.read() {
58 match guard.deref() {
59 CachePolicy::None => (None, None),
60 CachePolicy::Full => (Some(cache), Some(cache)),
61 CachePolicy::Read => (Some(cache), None),
62 CachePolicy::Update => (None, Some(cache)),
63 }
64 } else {
65 (None, None)
66 };
67
68 let path = request.url().path().to_owned();
69
70 let mut response = None;
72 if let Some(cache) = read_cache {
73 response = cache.get(&path);
74 }
75 let needs_cache_write = response.is_none();
76 let response = match response {
77 Some(response) => response,
78 None => {
79 config
80 .limiter
81 .until_ready_with_jitter(Jitter::new(
82 Duration::from_millis(0),
83 Duration::from_millis(50),
84 ))
85 .await;
86 config
87 .client
88 .execute(request)
89 .await?
90 .error_for_status()?
91 .bytes()
92 .await?
93 }
94 };
95
96 if let Some(cache) = write_cache
98 && needs_cache_write
99 {
100 cache.set(&path, &response);
101 }
102
103 Ok(serde_json::from_slice(&response)?)
104}