uranium_rs/
lib.rs

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