1#![deny(missing_docs)]
2#![cfg_attr(test, deny(warnings))]
3
4use crate::api::types::account::{AccountData, AccountInfo, UserData};
22use crate::api::types::epic_asset::EpicAsset;
23use crate::api::types::fab_asset_manifest::DownloadInfo;
24use crate::api::types::friends::Friend;
25use crate::api::{EpicAPI};
26
27use api::types::asset_info::{AssetInfo, GameToken};
28use api::types::asset_manifest::AssetManifest;
29use api::types::download_manifest::DownloadManifest;
30use api::types::entitlement::Entitlement;
31use api::types::library::Library;
32use log::{error, info, warn};
33use crate::api::error::EpicAPIError;
34
35pub mod api;
37
38#[derive(Default, Debug, Clone)]
40pub struct EpicGames {
41 egs: EpicAPI,
42}
43
44impl EpicGames {
45 pub fn new() -> Self {
47 EpicGames {
48 egs: EpicAPI::new(),
49 }
50 }
51
52 pub fn is_logged_in(&self) -> bool {
54 if let Some(exp) = self.egs.user_data.expires_at {
55 let now = chrono::offset::Utc::now();
56 let td = exp - now;
57 if td.num_seconds() > 600 {
58 return true;
59 }
60 }
61 false
62 }
63
64 pub fn user_details(&self) -> UserData {
66 self.egs.user_data.clone()
67 }
68
69 pub fn set_user_details(&mut self, user_details: UserData) {
71 self.egs.user_data.update(user_details);
72 }
73
74 pub async fn auth_code(
76 &mut self,
77 exchange_token: Option<String>,
78 authorization_code: Option<String>,
79 ) -> bool {
80 self.egs
81 .start_session(exchange_token, authorization_code)
82 .await
83 .unwrap_or(false)
84 }
85
86 pub async fn logout(&mut self) -> bool {
88 self.egs.invalidate_sesion().await
89 }
90
91 pub async fn login(&mut self) -> bool {
93 if let Some(exp) = self.egs.user_data.expires_at {
94 let now = chrono::offset::Utc::now();
95 let td = exp - now;
96 if td.num_seconds() > 600 {
97 info!("Trying to re-use existing login session... ");
98 match self.egs.resume_session().await {
99 Ok(b) => {
100 if b {
101 info!("Logged in");
102 return true;
103 }
104 return false;
105 }
106 Err(e) => {
107 warn!("{}", e)
108 }
109 };
110 }
111 }
112 info!("Logging in...");
113 if let Some(exp) = self.egs.user_data.refresh_expires_at {
114 let now = chrono::offset::Utc::now();
115 let td = exp - now;
116 if td.num_seconds() > 600 {
117 match self.egs.start_session(None, None).await {
118 Ok(b) => {
119 if b {
120 info!("Logged in");
121 return true;
122 }
123 return false;
124 }
125 Err(e) => {
126 error!("{}", e)
127 }
128 }
129 }
130 }
131 false
132 }
133
134 pub async fn list_assets(
136 &mut self,
137 platform: Option<String>,
138 label: Option<String>,
139 ) -> Vec<EpicAsset> {
140 self.egs
141 .assets(platform, label)
142 .await
143 .unwrap_or_else(|_| Vec::new())
144 }
145
146 pub async fn asset_manifest(
148 &mut self,
149 platform: Option<String>,
150 label: Option<String>,
151 namespace: Option<String>,
152 item_id: Option<String>,
153 app: Option<String>,
154 ) -> Option<AssetManifest> {
155 match self
156 .egs
157 .asset_manifest(platform, label, namespace, item_id, app)
158 .await
159 {
160 Ok(a) => Some(a),
161 Err(_) => None,
162 }
163 }
164
165 pub async fn fab_asset_manifest(
167 &self,
168 artifact_id: &str,
169 namespace: &str,
170 asset_id: &str,
171 platform: Option<&str>,
172 ) -> Result<Vec<DownloadInfo>, EpicAPIError> {
173 match self
174 .egs
175 .fab_asset_manifest(artifact_id, namespace, asset_id, platform)
176 .await
177 {
178 Ok(a) => Ok(a),
179 Err(e) => Err(e),
180 }
181 }
182
183 pub async fn asset_info(&mut self, asset: EpicAsset) -> Option<AssetInfo> {
185 match self.egs.asset_info(asset.clone()).await {
186 Ok(mut a) => a.remove(asset.catalog_item_id.as_str()),
187 Err(_) => None,
188 }
189 }
190
191 pub async fn account_details(&mut self) -> Option<AccountData> {
193 match self.egs.account_details().await {
194 Ok(a) => Some(a),
195 Err(_) => None,
196 }
197 }
198
199 pub async fn account_ids_details(&mut self, ids: Vec<String>) -> Option<Vec<AccountInfo>> {
201 match self.egs.account_ids_details(ids).await {
202 Ok(a) => Some(a),
203 Err(_) => None,
204 }
205 }
206
207 pub async fn account_friends(&mut self, include_pending: bool) -> Option<Vec<Friend>> {
209 match self.egs.account_friends(include_pending).await {
210 Ok(a) => Some(a),
211 Err(_) => None,
212 }
213 }
214
215 pub async fn game_token(&mut self) -> Option<GameToken> {
217 match self.egs.game_token().await {
218 Ok(a) => Some(a),
219 Err(_) => None,
220 }
221 }
222
223 pub async fn ownership_token(&mut self, asset: EpicAsset) -> Option<String> {
225 match self.egs.ownership_token(asset).await {
226 Ok(a) => Some(a.token),
227 Err(_) => None,
228 }
229 }
230
231 pub async fn user_entitlements(&mut self) -> Vec<Entitlement> {
233 self.egs.user_entitlements().await.unwrap_or_else(|_| Vec::new())
234 }
235
236 pub async fn library_items(&mut self, include_metadata: bool) -> Option<Library> {
238 match self.egs.library_items(include_metadata).await {
239 Ok(a) => Some(a),
240 Err(_) => None,
241 }
242 }
243
244 pub async fn fab_library_items(
246 &mut self,
247 account_id: String,
248 ) -> Option<api::types::fab_library::FabLibrary> {
249 match self.egs.fab_library_items(account_id).await {
250 Ok(a) => Some(a),
251 Err(_) => None,
252 }
253 }
254
255 pub async fn asset_download_manifests(&self, manifest: AssetManifest) -> Vec<DownloadManifest> {
257 self.egs.asset_download_manifests(manifest).await
258 }
259
260 pub async fn fab_download_manifest(
262 &self,
263 download_info: DownloadInfo,
264 distribution_point_url: &str,
265 ) -> Result<DownloadManifest, EpicAPIError> {
266 self.egs
267 .fab_download_manifest(download_info, distribution_point_url)
268 .await
269 }
270}