egs_api/api/
fab.rs

1use crate::api::error::EpicAPIError;
2use crate::api::types::download_manifest::DownloadManifest;
3use crate::api::types::fab_asset_manifest::DownloadInfo;
4use crate::api::types::fab_library::FabLibrary;
5use crate::api::EpicAPI;
6use log::{debug, error, warn};
7use std::borrow::BorrowMut;
8use std::str::FromStr;
9use url::Url;
10
11impl EpicAPI {
12    pub async fn fab_asset_manifest(
13        &self,
14        artifact_id: &str,
15        namespace: &str,
16        asset_id: &str,
17        platform: Option<&str>,
18    ) -> Result<Vec<DownloadInfo>, EpicAPIError> {
19        let url = format!("https://www.fab.com/e/artifacts/{}/manifest", artifact_id);
20        match self
21            .authorized_post_client(Url::parse(&url).unwrap())
22            .json(&serde_json::json!({
23                "item_id": asset_id,
24                "namespace": namespace,
25                "platform": platform.unwrap_or("Windows"),
26            }))
27            .send()
28            .await
29        {
30            Ok(response) => {
31                if response.status() == reqwest::StatusCode::OK {
32                    let text = response.text().await.unwrap();
33                    match serde_json::from_str::<
34                        crate::api::types::fab_asset_manifest::FabAssetManifest,
35                    >(&text)
36                    {
37                        Ok(manifest) => Ok(manifest.download_info),
38                        Err(e) => {
39                            error!("{:?}", e);
40                            debug!("{}", text);
41                            Err(EpicAPIError::Unknown)
42                        }
43                    }
44                } else if response.status() == reqwest::StatusCode::FORBIDDEN {
45                    Err(EpicAPIError::FabTimeout)
46                } else {
47                    debug!("{:?}", response.headers());
48                    warn!(
49                        "{} result: {}",
50                        response.status(),
51                        response.text().await.unwrap()
52                    );
53                    Err(EpicAPIError::Unknown)
54                }
55            }
56            Err(e) => {
57                error!("{:?}", e);
58                Err(EpicAPIError::Unknown)
59            }
60        }
61    }
62
63    pub async fn fab_download_manifest(
64        &self,
65        download_info: DownloadInfo,
66        distribution_point_url: &str,
67    ) -> Result<DownloadManifest, EpicAPIError> {
68        match download_info.get_distribution_point_by_base_url(distribution_point_url) {
69            None => {
70                error!("Distribution point not found");
71                Err(EpicAPIError::Unknown)
72            }
73            Some(point) => {
74                if point.signature_expiration < time::OffsetDateTime::now_utc() {
75                    error!("Expired signature");
76                    Err(EpicAPIError::Unknown)
77                } else {
78                    let client = EpicAPI::build_client().build().unwrap();
79                    match client
80                        .get(Url::from_str(&point.manifest_url).unwrap())
81                        .send()
82                        .await
83                    {
84                        Ok(response) => {
85                            if response.status() == reqwest::StatusCode::OK {
86                                match response.bytes().await {
87                                    Ok(data) => match DownloadManifest::parse(data.to_vec()) {
88                                        None => {
89                                            error!("Unable to parse the Download Manifest");
90                                            Err(EpicAPIError::Unknown)
91                                        }
92                                        Some(man) => Ok(man),
93                                    },
94                                    Err(_) => Err(EpicAPIError::Unknown),
95                                }
96                            } else {
97                                warn!(
98                                    "{} result: {}",
99                                    response.status(),
100                                    response.text().await.unwrap()
101                                );
102                                Err(EpicAPIError::Unknown)
103                            }
104                        }
105                        Err(_) => Err(EpicAPIError::Unknown),
106                    }
107                }
108            }
109        }
110    }
111
112    pub async fn fab_library_items(
113        &mut self,
114        account_id: String,
115    ) -> Result<FabLibrary, EpicAPIError> {
116        let mut library = FabLibrary::default();
117
118        loop {
119            let url = match &library.cursors.next {
120                None => {
121                    format!(
122                        "https://www.fab.com/e/accounts/{}/ue/library?count=100",
123                        account_id
124                    )
125                }
126                Some(c) => {
127                    format!(
128                        "https://www.fab.com/e/accounts/{}/ue/library?cursor={}&count=100",
129                        account_id, c
130                    )
131                }
132            };
133
134            match self
135                .authorized_get_client(Url::parse(&url).unwrap())
136                .send()
137                .await
138            {
139                Ok(response) => {
140                    if response.status() == reqwest::StatusCode::OK {
141                        let text = response.text().await.unwrap();
142                        match serde_json::from_str::<FabLibrary>(&text) {
143                            Ok(mut api_library) => {
144                                library.cursors.next = api_library.cursors.next;
145                                library.results.append(api_library.results.borrow_mut());
146                            }
147                            Err(e) => {
148                                error!("{:?}", e);
149                                debug!("{}", text);
150                                library.cursors.next = None;
151                            }
152                        }
153                    } else {
154                        debug!("{:?}", response.headers());
155                        warn!(
156                            "{} result: {}",
157                            response.status(),
158                            response.text().await.unwrap()
159                        );
160                    }
161                }
162                Err(e) => {
163                    error!("{:?}", e);
164                    library.cursors.next = None;
165                }
166            }
167            if library.cursors.next.is_none() {
168                break;
169            }
170        }
171
172        Ok(library)
173    }
174}