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