Skip to main content

uranium_rs/
lib.rs

1#![forbid(unsafe_code)]
2
3//! # uranium
4//!
5//! The `uranium` crate provides an easy, high-level API for:
6//! - Downloading Minecraft instances, mods from Rinth/Curse
7//! - Making a modpack from a given directory
8//! - Update a modpack from a given directory
9//!
10//!
11//! Also, `uranium` provides high modularity level when it comes to downloaders.
12//! Through the [`FileDownloader`](downloaders) trait.
13//!
14//! When using downloaders such as [`RinthDownloader`] it takes
15//! a generic parameter `T: FileDownloader`, so **YOU** the user can implement
16//! your own downloader if you dislike mine :( or thinks you can do a faster
17//! one.
18//!
19//! ``` rust no_run
20//! # async fn x() {
21//! use uranium_rs::downloaders::{Downloader, RinthDownloader};
22//!
23//! let mut rinth = RinthDownloader::<Downloader>::new("path", "destination").unwrap();
24//!
25//! if let Err(e) = rinth.complete().await {
26//!     println!("Something went wrong: {e}")
27//! } else {
28//!     println!("Download complete!")
29//! }
30//! # }
31//! ```
32//!
33//!
34//! This crate is under development so breaking changes may occur in later
35//! versions, but I'll try to avoid them.
36
37use std::path::Path;
38
39use downloaders::{
40    CurseDownloader, Downloader, FileDownloader, MinecraftDownloader as MD, RinthDownloader,
41};
42use error::{Result, UraniumError};
43use log::info;
44use modpack_maker::{ModpackMaker, State};
45use variables::constants::*;
46pub use mine_data_structs;
47
48pub mod downloaders;
49pub mod error;
50pub mod modpack_maker;
51pub mod version_checker;
52pub mod installation_fixer;
53
54mod code_functions;
55mod hashes;
56mod variables;
57
58/// # Easy to go function
59///
60/// This function will make a Modpack from the
61/// given path.
62///
63/// # Errors
64/// This function will return a `MakeError` in case the modpack can't
65/// be made for any reason.
66pub async fn make_modpack<I: AsRef<Path>, J: AsRef<Path>>(
67    minecraft_path: I,
68    modpack_name: J,
69) -> Result<()> {
70    let mut maker = ModpackMaker::new(&minecraft_path, modpack_name);
71    let mut i = 0;
72    loop {
73        match maker.progress().await {
74            Ok(State::Finish) => return Ok(()),
75            Err(e) => return Err(e),
76            _ => {
77                info!("{}", i);
78                i += 1;
79            }
80        }
81    }
82
83    //ModpackMaker::make(&minecraft_path).await
84}
85
86/// # Easy to go function
87///
88/// This function will download the modpack specified by `file_path`
89/// into `destination_path`
90///
91/// If there is no mods and/or config folder inside `destination_path` then they
92/// will be created.
93///
94///
95/// # Errors
96/// This function will return an `UraniumError` in case the download
97/// fails or when one or more paths are wrong.
98pub async fn curse_pack_download<I: AsRef<Path>, J: AsRef<Path>>(
99    file_path: I,
100    destination_path: J,
101) -> Result<()> {
102    let mut curse_downloader =
103        CurseDownloader::<Downloader>::new(&file_path, &destination_path).await?;
104    curse_downloader
105        .complete()
106        .await?;
107    Ok(())
108}
109
110/// # Easy to go function
111///
112/// This function will download the modpack specified by `file_path`
113/// into `destination_path`
114///
115/// If there is no mods and/or config folder inside `destination_path` then they
116/// will be created.
117///
118///
119/// # Errors
120/// This function will return an `UraniumError` in case the download
121/// fails or when one or more paths are wrong.
122pub async fn rinth_pack_download<I: AsRef<Path>, J: AsRef<Path>>(
123    file_path: I,
124    destination_path: J,
125) -> Result<()> {
126    let mut rinth_downloader = RinthDownloader::<Downloader>::new(&file_path, &destination_path)?;
127    rinth_downloader
128        .complete()
129        .await?;
130    Ok(())
131}
132
133/// # Easy to go function
134///
135/// This function still work in progress
136///
137/// # Errors
138/// This function will return an `Err(UraniumError)` in case the
139/// `MinecraftDownloader` has an error during the download.
140pub async fn download_minecraft<I: AsRef<Path>>(instance: &str, destination_path: I) -> Result<()> {
141    let mut minecraft_downloader = MD::<Downloader>::init(destination_path, instance).await?;
142    minecraft_downloader
143        .start()
144        .await?;
145    Ok(())
146}
147
148/// This function will set the max number of threads allowed to use.
149///
150/// Use it carefully, a big number of threads may decrease the performance.
151/// The default number of threads is 32.
152///
153/// In case the number of threads can't be updated this function will return
154/// None, in case of success Some(()) is returned.
155pub fn set_threads(t: usize) -> Option<()> {
156    let mut aux = NTHREADS.write().ok()?;
157    *aux = t;
158    Some(())
159}
160
161/// Init the logger and make a log.txt file to write logs content.
162///
163/// If this function is not called then there will be no
164/// log.txt or any kind of debug info/warn/warning message will
165/// be show in console.
166///
167/// # Panics
168/// Will panic in case log files or `CombinedLogger` cant be created.
169pub fn init_logger() -> Result<()> {
170    use std::fs::File;
171
172    use chrono::prelude::Local;
173    use simplelog::{
174        ColorChoice, CombinedLogger, Config, LevelFilter, TermLogger, TerminalMode, WriteLogger,
175    };
176
177    let home_dir = dirs::home_dir().ok_or(UraniumError::OtherWithReason(
178        "Cant get user home directory".to_string(),
179    ))?;
180
181    let log_file_name = home_dir
182        .join(".uranium")
183        .join(format!("log_{}", Local::now().format("%H-%M-%S_%d-%m-%Y")));
184
185    let latest_log_file = home_dir
186        .join(".uranium")
187        .join("latest_log_file.txt");
188
189    CombinedLogger::init(vec![
190        TermLogger::new(
191            LevelFilter::Info,
192            Config::default(),
193            TerminalMode::Mixed,
194            ColorChoice::Auto,
195        ),
196        WriteLogger::new(
197            LevelFilter::Info,
198            Config::default(),
199            File::create(log_file_name)?,
200        ),
201        WriteLogger::new(
202            LevelFilter::Info,
203            Config::default(),
204            File::create(latest_log_file)?,
205        ),
206    ])
207    .unwrap();
208    Ok(())
209}
210
211#[cfg(test)]
212mod tests {}