modio/lib.rs
1//! Modio provides a set of building blocks for interacting with the [mod.io](https://mod.io) API.
2//!
3//! The client uses asynchronous I/O, backed by the `futures` and `tokio` crates, and requires both
4//! to be used alongside.
5//!
6//! # Authentication
7//!
8//! To access the API authentication is required and can be done via several ways:
9//!
10//! - Request an [API key (Read-only)](https://mod.io/me/access)
11//! - Manually create an [OAuth 2 Access Token (Read + Write)](https://mod.io/me/access#oauth)
12//! - [Email Authentication Flow](auth::Auth#example) to create an OAuth 2 Access Token (Read + Write)
13//! - [External Authentication](auth::Auth::external) to create an OAuth 2 Access Token (Read + Write)
14//! automatically on platforms such as Steam, GOG, itch.io, Switch, Xbox, Discord and Oculus.
15//!
16//! # Rate Limiting
17//!
18//! - API keys linked to a game have **unlimited requests**.
19//! - API keys linked to a user have **60 requests per minute**.
20//! - OAuth2 user tokens are limited to **120 requests per minute**.
21//!
22//! [`Error::is_ratelimited`] will return true
23//! if the rate limit associated with credentials has been exhausted.
24//!
25//! # Example: Basic setup
26//!
27//! ```no_run
28//! use modio::{Credentials, Modio};
29//!
30//! #[tokio::main]
31//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
32//! let modio = Modio::new(Credentials::new("user-or-game-api-key"))?;
33//!
34//! // create some tasks and execute them
35//! // let result = task.await?;
36//! Ok(())
37//! }
38//! ```
39//!
40//! For testing purposes use [`Modio::host`] to create a client for the
41//! mod.io [test environment](https://docs.mod.io/restapiref/#testing).
42//!
43//! # Example: Chaining api requests
44//!
45//! ```no_run
46//! use futures_util::future::try_join3;
47//! use modio::filter::Filter;
48//! use modio::types::id::Id;
49//! # #[tokio::main]
50//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
51//! # let modio = modio::Modio::new("user-or-game-api-key")?;
52//!
53//! // OpenXcom: The X-Com Files
54//! let modref = modio.mod_(Id::new(51), Id::new(158));
55//!
56//! // Get mod with its dependencies and all files
57//! let deps = modref.dependencies().list();
58//! let files = modref.files().search(Filter::default()).collect();
59//! let mod_ = modref.get();
60//!
61//! let (m, deps, files) = try_join3(mod_, deps, files).await?;
62//!
63//! println!("{}", m.name);
64//! println!(
65//! "deps: {:?}",
66//! deps.into_iter().map(|d| d.mod_id).collect::<Vec<_>>()
67//! );
68//! for file in files {
69//! println!("file id: {} version: {:?}", file.id, file.version);
70//! }
71//! # Ok(())
72//! # }
73//! ```
74//!
75//! # Example: Downloading mods
76//!
77//! ```no_run
78//! use modio::download::{DownloadAction, ResolvePolicy};
79//! use modio::types::id::Id;
80//! # #[tokio::main]
81//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
82//! # let modio = modio::Modio::new("user-or-game-api-key")?;
83//!
84//! // Download the primary file of a mod.
85//! let action = DownloadAction::Primary {
86//! game_id: Id::new(5),
87//! mod_id: Id::new(19),
88//! };
89//! modio
90//! .download(action)
91//! .await?
92//! .save_to_file("mod.zip")
93//! .await?;
94//!
95//! // Download the specific file of a mod.
96//! let action = DownloadAction::File {
97//! game_id: Id::new(5),
98//! mod_id: Id::new(19),
99//! file_id: Id::new(101),
100//! };
101//! modio
102//! .download(action)
103//! .await?
104//! .save_to_file("mod.zip")
105//! .await?;
106//!
107//! // Download the specific version of a mod.
108//! // if multiple files are found then the latest file is downloaded.
109//! // Set policy to `ResolvePolicy::Fail` to return with
110//! // `modio::download::Error::MultipleFilesFound` as source error.
111//! let action = DownloadAction::Version {
112//! game_id: Id::new(5),
113//! mod_id: Id::new(19),
114//! version: "0.1".to_string(),
115//! policy: ResolvePolicy::Latest,
116//! };
117//! modio
118//! .download(action)
119//! .await?
120//! .save_to_file("mod.zip")
121//! .await?;
122//! # Ok(())
123//! # }
124//! ```
125#![doc(html_root_url = "https://docs.rs/modio/0.12.1")]
126#![deny(rust_2018_idioms)]
127#![deny(rustdoc::broken_intra_doc_links)]
128#![allow(clippy::upper_case_acronyms)]
129
130#[macro_use]
131mod macros;
132
133pub mod auth;
134#[macro_use]
135pub mod filter;
136pub mod comments;
137pub mod download;
138pub mod files;
139pub mod games;
140pub mod metadata;
141pub mod mods;
142pub mod reports;
143pub mod teams;
144pub mod types;
145pub mod user;
146
147mod client;
148mod error;
149mod file_source;
150mod loader;
151mod request;
152mod routing;
153
154pub use crate::auth::Credentials;
155pub use crate::client::{Builder, Modio};
156pub use crate::download::DownloadAction;
157pub use crate::error::{Error, Result};
158pub use crate::loader::{Page, Query};
159pub use crate::types::{Deletion, Editing, TargetPlatform, TargetPortal};
160
161mod prelude {
162 pub use futures_util::Stream;
163 pub use reqwest::multipart::Form;
164 pub use reqwest::StatusCode;
165
166 pub use crate::filter::Filter;
167 pub use crate::loader::Query;
168 pub use crate::routing::Route;
169 pub use crate::types::Message;
170 pub use crate::{Deletion, Editing, Modio, Result};
171}
172
173/// Re-exports of the used reqwest types.
174#[doc(hidden)]
175pub mod lib {
176 pub use reqwest::header;
177 pub use reqwest::redirect::Policy;
178 pub use reqwest::ClientBuilder;
179 #[cfg(feature = "__tls")]
180 pub use reqwest::{Certificate, Identity};
181 pub use reqwest::{Proxy, Url};
182}