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 {}