From 7490d125248fb9846dda046352b5ddfd71bfd5d2 Mon Sep 17 00:00:00 2001 From: TOwInOK <60252419+TOwInOK@users.noreply.github.com> Date: Sat, 25 May 2024 23:20:27 +0700 Subject: [PATCH] fixed #11 Make the hash vector much smaller fixed #10 Implemented dictionary for pb (Progress bar) #7 Edit ReadMe Add many tracies (debug, trace, info) change some errors make 'de toml erros more pretty --- .DS_Store | Bin 0 -> 6148 bytes Cargo.lock | 153 ++++++++++++++++------------- Cargo.toml | 3 + README.md | 12 ++- language.toml | 22 +++++ language_ru-example.toml | 22 +++++ settings.toml | 6 +- settings_example.toml | 28 +++--- src/dictionary/mod.rs | 1 + src/dictionary/pb_messages.rs | 71 +++++++++++++ src/errors/error.rs | 50 +++++----- src/lock/ext.rs | 3 +- src/lock/mod.rs | 73 +++++++++----- src/main.rs | 4 +- src/mananger/download.rs | 9 +- src/mananger/manage.rs | 19 ++-- src/mananger/mod.rs | 68 +++++++++++-- src/mananger/watch_changer.rs | 44 ++++++--- src/models/cores/paper.rs | 14 ++- src/models/extensions/modrinth.rs | 74 +++++++++----- src/settings/additions.rs | 10 +- src/settings/core.rs | 92 ++++++++++------- src/settings/extensions/plugin.rs | 9 ++ src/settings/extensions/plugins.rs | 133 +++++++++++++++---------- src/tr/delete.rs | 18 ++++ src/tr/download.rs | 77 ++++++++++----- src/tr/hash.rs | 21 ++-- src/tr/load.rs | 36 +++++-- src/tr/mod.rs | 1 + src/tr/save.rs | 62 ++++++------ 30 files changed, 759 insertions(+), 376 deletions(-) create mode 100644 .DS_Store create mode 100644 language.toml create mode 100644 language_ru-example.toml create mode 100644 src/dictionary/mod.rs create mode 100644 src/dictionary/pb_messages.rs create mode 100644 src/tr/delete.rs diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ef366d7b5c671900c7815d56853fd058c62c2150 GIT binary patch literal 6148 zcmeHK&ubGw6n>M$Cfi!b!9qcV1+QgIOHhgkX__89cssuNKSiLtVc>;~g@PHR>& zHFtqR^&!clm?ZV-V$IuDSOu&C|C$2)?QYX4^=Lvve7V=(@AFvpgIES==gr{+>De!3 zC>1#wm?Me{oNon=bGdf7B>_a<-n>7|r$a8>RF zucE=MTfcWIldKmdgNY(U;Q%ggUq?wOXKgu6!c=j6-QYMir(55j&zpx&4&3HZV{zcl zkB=HCKW;7-PHpeuqo?QHi+GgC&sYIWV82ziYw!wKkAeoD{7DkaWQZ1KIdo2Eh-Zgh z06oMlTve&Wp3AY`r4$j!@MBGfc-jy@;)s7;ir?NEvx}ZC5yz2=(_mvy{Jt&sR7Ot| z>aWgJJScc=VUGGu#(WFDtjuzcc)aCi-l5vgE!V*=-zs1gSXY4e2N#L4WiZ#Mwhm get error) +provider = "paper" # [vanilla, paper, folia, purpur, fabric, waterfall, velocity] +version = "1.20.6" # Or Latest (latest -> get error) force_update = true # Optional [plugins.name] # name be used only in kebab-case -source = "modrinth" # [hangar, modrinth] => modrinth by default -version = "ffdfdsd" # numbers of this version. -channel = "release" # [release, beta, alpha] => release -freeze = false # false || true => false by default +source = "modrinth" # [hangar, modrinth] => modrinth by default +version = "ffdfdsd" # numbers of this version. +channel = "release" # [release, beta, alpha] => release +freeze = false # false || true => false by default force_update = false # false || true => false by default # Optional -[mods.name] # name be used only in kebab-case -source = "modrinth" # [hangar, modrinth] => modrinth by default -version = "ffdfdsd" # numbers of this version. -channel = "release" # [release, beta, alpha] => release -freeze = false # false || true => false by default +[mods.name] # name be used only in kebab-case ^Not implemented!!! +source = "modrinth" # [hangar, modrinth] => modrinth by default +version = "ffdfdsd" # numbers of this version. +channel = "release" # [release, beta, alpha] => release +freeze = false # false || true => false by default force_update = false # false || true => false by default # Optional [additions] -source = "git@github.com:Username/Super-Config.git" # Optional, require for key -key = "MySuperMegaKey" # Optional, don't work without link -duraction = 300 # Optional, value of duraction between manager checker iterations (in seconds) +source = "git@github.com:Username/Super-Config.git" # Optional, require for key ^Not implemented!!! +key = "MySuperMegaKey" # Optional, don't work without link ^Not implemented!!! +duraction = 300 # Optional, value of duraction between manager check iterations (in seconds) => 300 by default diff --git a/src/dictionary/mod.rs b/src/dictionary/mod.rs new file mode 100644 index 0000000..a178bd8 --- /dev/null +++ b/src/dictionary/mod.rs @@ -0,0 +1 @@ +pub mod pb_messages; diff --git a/src/dictionary/pb_messages.rs b/src/dictionary/pb_messages.rs new file mode 100644 index 0000000..3d714f3 --- /dev/null +++ b/src/dictionary/pb_messages.rs @@ -0,0 +1,71 @@ +use serde::{Deserialize, Serialize}; + +use crate::tr::load::Load; + +#[derive(Deserialize, Serialize)] +pub struct PbMessages { + pub calculate_hash: String, + pub delete_exist_version: String, + pub doest_need_to_update: String, + pub done: String, + pub download_file: String, + pub file_downloaded: String, + pub restart: String, + pub saving_file: String, + pub start_new_iteration: String, + pub stop_iteration: String, + pub waiting_new_iteration: String, + pub write_to_lock: String, + // Config + pub find_changes_in_settings: String, + pub settings_changed: String, + pub settings_has_rewrited: String, + pub settings_same: String, + // Intro + pub intro: String, + // Models messages + pub init_work: String, + pub finding_version: String, + pub make_link: String, + // Remove nonexist + pub start_remove_nonexist: String, + pub remove_nonexist: String, +} + +impl Default for PbMessages { + fn default() -> Self { + Self { + restart: "Restart...".into(), + stop_iteration: "Stop iteration!".into(), + start_new_iteration: "Start new iteration!".into(), + waiting_new_iteration: "Waiting new iteration...".into(), + doest_need_to_update: "Does't need to update!".into(), + delete_exist_version: "Delete exist version!".into(), + download_file: "Download file...".into(), + saving_file: "Saving file...".into(), + write_to_lock: "Write to lock!".into(), + done: "Done!".into(), + file_downloaded: "File downloaded!".into(), + calculate_hash: "Calculate hash...".into(), + find_changes_in_settings: "Find some changes in settings!".into(), + settings_changed: "Settings changed".into(), + settings_has_rewrited: "Settings has rewrited".into(), + settings_same: "Settings same".into(), + intro: "MAC ready to work!".into(), + init_work: "Generating link...".into(), + finding_version: "Finding version...".into(), + make_link: "Make link...".into(), + start_remove_nonexist: "Start remove nonexist".into(), + remove_nonexist: "Remove nonexist".into(), + } + } +} +impl PbMessages { + pub fn remove_if_nonexist(&self, name: &str) -> String { + format!("{}: {}", self.remove_nonexist, name) + } +} + +impl Load for PbMessages { + const PATH: &'static str = "language.toml"; +} diff --git a/src/errors/error.rs b/src/errors/error.rs index a467dc4..65922b8 100644 --- a/src/errors/error.rs +++ b/src/errors/error.rs @@ -4,8 +4,8 @@ use crate::mananger::messages::Messages; #[derive(Error, Debug)] pub enum CompareHashError { - #[error("Хэш не совпадает")] - HashNotCompare(), + #[error("Хэш не совпадает: expect => {0}, value => {1}")] + HashNotCompare(String, String), #[error("Конвертация Sha1 проведена не успешно : {0}")] SHA1(std::io::Error), #[error("Конвертация Sha256 проведена не успешно : {0}")] @@ -18,22 +18,20 @@ pub enum CompareHashError { #[derive(Error, Debug)] pub enum Error { - #[error("Проблема с обработкой запроса: {0}")] + #[error("Reqwest error: {0}")] Reqwest(#[from] reqwest::Error), - #[error("Проблема с обработкой хэша: {0}")] + #[error("Hash corrupted: {0}")] CompareHash(CompareHashError), - // #[error("Проблема с скачиванием файла: {0}")] - // Download(String), - #[error("Ошибка ввода/вывода: {0}")] + #[error("IO error: {0}")] Io(#[from] std::io::Error), - #[error("{0}")] + #[error("TOML parse error{0}")] TomlParse(String), - #[error("Ошибка сериализация TOML: {0}")] + #[error("Serialization of TOML error: {0}")] TomlSerialize(#[from] toml::ser::Error), - #[error("Не удалось найти: {0}")] + #[error("Not found: {0}")] NotFound(String), - #[error("Ошибка: {0}")] - Any(#[from] Box), + // #[error("Any error: {0}")] + // Any(#[from] Box), #[error("Task join error: {0}")] JoinError(#[from] tokio::task::JoinError), #[error("Indicatif template error: {0}")] @@ -48,18 +46,20 @@ impl From for Error { let value = value.to_string(); let parts: Vec<&str> = value.split('|').collect(); - // Проверяем, что индексы существуют и выбираем только нужные let message = if parts.len() >= 4 { - let third_part = parts[3].trim(); - let trimmed_third_part = &third_part[2..]; // Удаляем первые три символа + let third_part: String = parts[3] + .trim() + .chars() + .filter(|x| *x != '^' || *x != '\\') + .collect(); format!( " Where => {} ||| What => {} ||| why => {} ", parts[0].trim(), parts[2].trim(), - trimmed_third_part + third_part ) } else { - value.to_string() // Если не удалось разделить на нужное количество частей, вернем исходную строку + value.to_string() }; Error::TomlParse(message) @@ -83,13 +83,6 @@ macro_rules! not_found_path { }; } -// #[macro_export] -// macro_rules! download_error { -// ($($arg:tt)*) => { -// Err(Error::Download(format!($($arg)*))) -// }; -// } - #[macro_export] macro_rules! not_found_build_error { ($arg:tt) => { @@ -116,3 +109,12 @@ macro_rules! not_found_plugin_error { ))) }; } +#[macro_export] +macro_rules! not_found_plugin_link_error { + ($arg:tt) => { + Err(Error::NotFound(format!( + "Not found link in for plugin: ->{}<-", + $arg + ))) + }; +} diff --git a/src/lock/ext.rs b/src/lock/ext.rs index 9eb93cf..82981fa 100644 --- a/src/lock/ext.rs +++ b/src/lock/ext.rs @@ -6,7 +6,8 @@ pub struct ExtensionMeta { path: String, } impl ExtensionMeta { - pub fn new(build: String, path: String) -> Self { + pub fn new(build: String, path: &str, name: &str) -> Self { + let path = format!("{}{}.jar", path, name); Self { build, path } } diff --git a/src/lock/mod.rs b/src/lock/mod.rs index 50c9ddf..858f42c 100644 --- a/src/lock/mod.rs +++ b/src/lock/mod.rs @@ -1,18 +1,28 @@ pub mod core; pub mod ext; +use indicatif::ProgressBar; +use log::debug; use serde::{Deserialize, Serialize}; -use tokio::sync::RwLockReadGuard; +use tokio::sync::RwLock; use self::core::CoreMeta; use self::ext::ExtensionMeta; -use crate::errors::error::Result; use crate::settings::Settings; +use crate::tr::delete::Delete; use crate::{ settings::core::Core, tr::{load::Load, save::Save}, }; -use std::{collections::HashMap, fs}; +use std::collections::HashMap; +use std::sync::Arc; + +use crate::dictionary::pb_messages::PbMessages; +use lazy_static::lazy_static; + +lazy_static! { + static ref DICT: PbMessages = PbMessages::load_sync().unwrap(); +} #[derive(Default, Serialize, Deserialize, Clone)] pub struct Lock { @@ -36,35 +46,44 @@ impl Lock { pub fn set_core(&mut self, value: Core, build: String) { self.core = value.to_meta(build); } - pub fn remove_plugin(&mut self, key: &str) -> Result<()> { - self.plugins.remove(key) + pub async fn remove_plugin(&mut self, key: &str) { + self.plugins.remove(key).await } - pub fn remove_mod(&mut self, key: &str) -> Result<()> { - self.mods.remove(key) + pub async fn remove_mod(&mut self, key: &str) { + self.mods.remove(key).await } //delete and make the current core the default - pub fn remove_core(&mut self) -> Result<()> { - fs::remove_file(self.core().path())?; + pub async fn remove_core(&mut self) { + //remove self.core = CoreMeta::default(); - Ok(()) } - pub fn remove_nonexistent(&mut self, settings: RwLockReadGuard) -> Result<()> { - let plugin_keys: Vec = self.plugins().0.keys().cloned().collect(); - // TODO: let mods_keys - if let Some(e) = settings.plugins() { - for key in plugin_keys { - if !e.items().contains_key(&key) { - self.remove_plugin(key.as_str())?; + pub async fn remove_nonexistent( + &mut self, + settings: Arc>, + pb: Arc, + ) { + debug!( + "fn() remove_nonexistent => keys list: {:#?}", + &self.plugins().0 + ); + pb.set_message(&DICT.start_remove_nonexist); + if let Some(settings_plugins) = settings.read().await.plugins() { + let lock_list = self.plugins().get_list().clone(); + for (key, _) in lock_list { + if !settings_plugins.items().contains_key(&key) { + pb.set_message(DICT.remove_if_nonexist(&key)); + debug!("{}", DICT.remove_if_nonexist(&key)); + self.remove_plugin(&key).await } } } // TODO: add remover for mods - Ok(()) } } #[derive(Default, Serialize, Deserialize, Clone)] pub struct ExtensionMetaList(HashMap); + impl ExtensionMetaList { pub fn get(&self, key: &str) -> Option<&ExtensionMeta> { self.0.get(key) @@ -72,17 +91,18 @@ impl ExtensionMetaList { pub fn insert(&mut self, key: String, value: ExtensionMeta) { self.0.insert(key, value); } - pub fn remove(&mut self, key: &str) -> Result<()> { - let value = self.0.remove(key); - match value { - Some(e) => Ok(fs::remove_file(e.path())?), - None => Ok(()), + // make it traited + pub async fn remove(&mut self, key: &str) { + if let Some(e) = self.0.remove(key) { + self.delete(e.path()).await } } - pub fn update(&mut self, key: String, value: ExtensionMeta) -> Result<()> { - self.remove(&key)?; + pub async fn update(&mut self, key: String, value: ExtensionMeta) { + self.remove(&key).await; self.insert(key, value); - Ok(()) + } + pub fn get_list(&self) -> &HashMap { + &self.0 } } @@ -92,3 +112,4 @@ impl Save for Lock { impl Load for Lock { const PATH: &'static str = "./lock.toml"; } +impl Delete for ExtensionMetaList {} diff --git a/src/main.rs b/src/main.rs index f3a8cf6..422cac1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +pub mod dictionary; pub mod errors; pub mod lock; pub mod mananger; @@ -10,8 +11,5 @@ use crate::errors::error::Result; #[tokio::main] async fn main() -> Result<()> { - pretty_env_logger::formatted_builder() - .filter_level(log::LevelFilter::Info) - .init(); mananger::run().await } diff --git a/src/mananger/download.rs b/src/mananger/download.rs index 8bd8210..7d04ac0 100644 --- a/src/mananger/download.rs +++ b/src/mananger/download.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use std::time::Duration; use indicatif::MultiProgress; +use log::error; use tokio::sync::{Mutex, RwLock}; use tokio::time::sleep; use tokio_util::sync::CancellationToken; @@ -22,8 +23,8 @@ pub async fn download( .additions() .unwrap_or(&Additions::default()) .duraction() - .unwrap_or(300f64); - let cooldown = Duration::from_secs_f64(duraction); + .unwrap_or(300); + let cooldown = Duration::from_secs(duraction); loop { '_core_scope: { let lock = Arc::clone(&lock); @@ -50,6 +51,10 @@ pub async fn download( mpb, ) .await + .map_err(|e| { + error!("Plugin scope error {:#?}", &e); + e + }) } else { Ok(()) } diff --git a/src/mananger/manage.rs b/src/mananger/manage.rs index e43b6c8..49819ad 100644 --- a/src/mananger/manage.rs +++ b/src/mananger/manage.rs @@ -1,13 +1,20 @@ +use crate::tr::load::Load; use std::sync::Arc; use indicatif::MultiProgress; use tokio::sync::{mpsc::Receiver, Mutex, RwLock}; use tokio_util::sync::CancellationToken; +use crate::dictionary::pb_messages::PbMessages; use crate::errors::error::Result; use crate::mananger::download::download; use crate::mananger::messages::Messages; use crate::{lock::Lock, settings::Settings}; +use lazy_static::lazy_static; + +lazy_static! { + static ref DICT: PbMessages = PbMessages::load_sync().unwrap(); +} pub async fn manage( mut rx: Receiver, @@ -23,26 +30,26 @@ pub async fn manage( tokio::select! { Some(e) = rx.recv() => match e { Messages::Restart(pb) => { - pb.set_message("Рестарт!"); + pb.set_message(&DICT.restart); let key = Arc::clone(&key); - pb.set_message("Стопаем текущюю задачу!"); + pb.set_message(&DICT.stop_iteration); key.cancel(); mpb.clear()?; if key.is_cancelled() { - pb.set_message("Начинаем новую!"); + pb.set_message(&DICT.start_new_iteration); tokio::spawn(download(settings.clone(), lock.clone(), mpb.clone(), key)); } else { - pb.set_message("Ну... она стоит"); + pb.set_message(&DICT.waiting_new_iteration); } pb.finish_and_clear(); } Messages::Stop(pb) => { - pb.finish_with_message("Остановка!"); + pb.finish_with_message(&DICT.stop_iteration); key.cancelled().await; } Messages::Start(pb) => { let key = Arc::clone(&key); - pb.finish_with_message("Начинаем новую!"); + pb.finish_with_message(&DICT.start_new_iteration); tokio::spawn(download(settings.clone(), lock.clone(), mpb.clone(), key)); pb.finish_and_clear(); } diff --git a/src/mananger/mod.rs b/src/mananger/mod.rs index 174725d..6436bb5 100644 --- a/src/mananger/mod.rs +++ b/src/mananger/mod.rs @@ -4,28 +4,46 @@ pub mod messages; mod watch_changer; use std::sync::Arc; +use std::time::Duration; +use self::watch_changer::watch_changes; +use crate::dictionary::pb_messages::PbMessages; use crate::errors::error::Result; +use crate::settings::extensions::plugin::Plugin; +use crate::tr::save::Save; +use crate::{lock, settings, tr}; use indicatif::{MultiProgress, ProgressBar}; +use indicatif_log_bridge::LogWrapper; +use lazy_static::lazy_static; use lock::Lock; use log::warn; use manage::manage; use settings::Settings; +use tokio::fs::{self, File}; +use tokio::io::AsyncWriteExt; +use tokio::time::sleep; use tokio::{ sync::{mpsc, Mutex, RwLock}, try_join, }; use tr::load::Load; -use crate::{lock, settings, tr}; - -use self::watch_changer::watch_changes; +lazy_static! { + static ref DICT: PbMessages = PbMessages::load_sync().unwrap(); +} pub async fn run() -> Result<()> { + let logger = pretty_env_logger::formatted_builder() + .filter_level(log::LevelFilter::Info) + .build(); let (mpb, lock, settings) = init().await?; - // + let mpb_cloned = mpb.as_ref().clone(); + LogWrapper::new(mpb_cloned, logger).try_init().unwrap(); + // Init It! let pb = mpb.add(ProgressBar::new_spinner()); - pb.finish_with_message("Init Minecraft Addon Controller"); + pb.set_message(&DICT.intro); + sleep(Duration::from_secs(1)).await; + pb.finish_and_clear(); // let (tx, rx) = mpsc::channel(20); @@ -50,11 +68,43 @@ pub async fn run() -> Result<()> { } async fn init() -> Result<(Arc, Arc>, Arc>)> { + '_plugin_folder_scope: { + if fs::read_dir(Plugin::PATH).await.is_err() { + fs::create_dir(Plugin::PATH).await? + } + } + '_default_settings_scope: { + let path = ::PATH; + if File::open(path).await.is_err() { + let default = Settings::default(); + warn!("Create default config file"); + let mut file = File::create(path).await?; + let toml_defefault = toml::to_string_pretty(&default)?; + file.write_all(toml_defefault.as_bytes()).await?; + } + } + '_default_lock_scope: { + let path = ::PATH; + if File::open(path).await.is_err() { + let default = Lock::default(); + warn!("Create default Lock file"); + let mut file = File::create(path).await?; + let toml_defefault = toml::to_string_pretty(&default)?; + file.write_all(toml_defefault.as_bytes()).await?; + } + } + '_default_language_scope: { + let path = ::PATH; + if File::open(path).await.is_err() { + let default = PbMessages::default(); + warn!("Create default language file"); + let mut file = File::create(path).await?; + let toml_defefault = toml::to_string_pretty(&default)?; + file.write_all(toml_defefault.as_bytes()).await?; + } + } let mpb: Arc = Arc::new(MultiProgress::new()); - let lock: Arc> = Arc::new(Mutex::new(Lock::load().await.unwrap_or({ - warn!("Use default Lock"); - Lock::default() - }))); + let lock: Arc> = Arc::new(Mutex::new(Lock::load().await?)); let settings = Arc::new(RwLock::new(Settings::load().await?)); Ok((mpb, lock, settings)) } diff --git a/src/mananger/watch_changer.rs b/src/mananger/watch_changer.rs index c2f02b9..d4d8c55 100644 --- a/src/mananger/watch_changer.rs +++ b/src/mananger/watch_changer.rs @@ -4,6 +4,7 @@ use std::time::Duration; use async_watcher::notify::RecursiveMode; use async_watcher::AsyncDebouncer; use indicatif::{MultiProgress, ProgressBar}; +use log::debug; use tokio::sync::mpsc::Sender; use tokio::sync::{Mutex, RwLock}; @@ -12,6 +13,12 @@ use crate::mananger::messages::Messages; use crate::tr::load::Load; use crate::{lock::Lock, settings::Settings}; +use crate::dictionary::pb_messages::PbMessages; +use lazy_static::lazy_static; + +lazy_static! { + static ref DICT: PbMessages = PbMessages::load_sync().unwrap(); +} /// Load downloader module. /// Always check config file. /// Use `token` for canceling minecraft task @@ -19,7 +26,7 @@ pub async fn watch_changes( settings: Arc>, lock: Arc>, mpb: Arc, - dw_tx: Sender, + manager_tx: Sender, ) -> Result<()> { const CONFIG_PATH: &str = "settings.toml"; // initialize the debouncer @@ -31,36 +38,43 @@ pub async fn watch_changes( .watch(CONFIG_PATH.as_ref(), RecursiveMode::NonRecursive) .unwrap(); + let pb = Arc::new(mpb.add(ProgressBar::new_spinner())); // Check lock { - lock.lock() - .await - .remove_nonexistent(settings.read().await)?; + debug!("Start remove_nonexistent"); + let pb = Arc::clone(&pb); + let settings = Arc::clone(&settings); + lock.lock().await.remove_nonexistent(settings, pb).await; } - let pb = Arc::new(mpb.add(ProgressBar::new_spinner())); // Send start to downloader { - dw_tx.send(Messages::Start(Arc::clone(&pb))).await?; + debug!("Start downloader (message)"); + let pb = Arc::clone(&pb); + manager_tx.send(Messages::Start(pb)).await?; } // wait for events while rx.recv().await.is_some() { + debug!("find iteration"); let pb = Arc::clone(&pb); - pb.set_message("Find some changes in config!"); - let settings = Arc::clone(&settings); + pb.set_message(&DICT.find_changes_in_settings); let settings_new = Settings::load().await?; + let settings = Arc::clone(&settings); if *settings.read().await != settings_new { - pb.set_message("настройки другие"); + pb.set_message(&DICT.settings_changed); *settings.write().await = settings_new; { - lock.lock() - .await - .remove_nonexistent(settings.read().await)?; + debug!("Start remove_nonexistent"); + let pb = Arc::clone(&pb); + lock.lock().await.remove_nonexistent(settings, pb).await; } - pb.set_message("настройки перезаписали"); - dw_tx.send(Messages::Restart(pb)).await?; + debug!("Start downloader (message)"); + pb.set_message(&DICT.settings_has_rewrited); + manager_tx.send(Messages::Restart(pb)).await?; } else { - pb.set_message("настройки теже"); + debug!("Nothing to update (config)"); + pb.set_message(&DICT.settings_same); + pb.finish_and_clear(); } } Ok(()) diff --git a/src/models/cores/paper.rs b/src/models/cores/paper.rs index 0334d2d..b29f6a6 100644 --- a/src/models/cores/paper.rs +++ b/src/models/cores/paper.rs @@ -1,6 +1,14 @@ use indicatif::ProgressBar; use serde::{Deserialize, Serialize}; +use crate::dictionary::pb_messages::PbMessages; +use crate::tr::load::Load; +use lazy_static::lazy_static; + +lazy_static! { + static ref DICT: PbMessages = PbMessages::load_sync().unwrap(); +} + use crate::{ errors::error::{Error, Result}, not_found_build_error, not_found_version_error, @@ -50,13 +58,13 @@ impl ModelCore for T { async fn get_link(core: &Core, pb: &ProgressBar) -> Result<(String, ChooseHash, String)> { let core_name = Self::CORE_NAME; // Start work - pb.set_message("Init work"); + pb.set_message(&DICT.init_work); //get data from core let build = core.build(); let version = core.version(); //find link and version - pb.set_message("Finding version"); + pb.set_message(&DICT.finding_version); let version = find_version(version, core_name).await?; let verlink = format!( @@ -64,7 +72,7 @@ impl ModelCore for T { core_name, version ); - pb.set_message("Make link"); + pb.set_message(&DICT.make_link); let build_list: BuildList = reqwest::get(verlink).await?.json().await?; let build_list = build_list.builds.as_slice(); diff --git a/src/models/extensions/modrinth.rs b/src/models/extensions/modrinth.rs index cd2ddd9..a3525c6 100644 --- a/src/models/extensions/modrinth.rs +++ b/src/models/extensions/modrinth.rs @@ -1,9 +1,10 @@ -use log::debug; +use log::trace; use serde::Deserialize; use serde::Serialize; use crate::errors::error::{Error, Result}; use crate::not_found_plugin_error; +use crate::not_found_plugin_link_error; use crate::settings::extensions::plugin::Plugin; use crate::tr::hash::ChooseHash; use crate::tr::model::extension::ModelExtensions; @@ -17,9 +18,9 @@ pub struct ModrinthData { //Always change ich version id: String, //Stable token. - project_id: String, + // project_id: String, files: Vec, - dependencies: Vec, + // dependencies: Vec, } #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -50,38 +51,57 @@ impl ModelExtensions for ModrinthData { game_version: &str, loader: &str, ) -> Result<(Self::Link, ChooseHash, Self::Version)> { - let link: String = { - // TODO: Make normal params! - match game_version { - "Latest" => { - let channel = ext.channel().get_str().await; - let link = format!("https://api.modrinth.com/v2/project/{}/version?&loaders=[\"{}\"]&featured=true&version_type={}", name, loader, channel); - debug!("Plugin: {} -> Link: {}", name, link); - link + let channel = ext.channel().get_str().await.to_string(); + let link = format!("https://api.modrinth.com/v2/project/{}/version", name); + + let loader = { + if loader.to_lowercase() == "purpur" { + "paper" + } else { + loader + } + }; + let query = { + match game_version.to_lowercase().as_str() { + "latest" => { + vec![ + // ("game_version", format!("[\"{}\"]", game_version)), + ("loaders", format!("[\"{}\"]", loader)), + ("featured", true.to_string()), + ("version_type", channel), + ] } + _ => { - let channel = ext.channel().get_str().await; - let link = format!("https://api.modrinth.com/v2/project/{}/version?game_versions=[\"{}\"]&loaders=[\"{}\"]&featured=true&version_type={}", name, game_version, loader, channel); - debug!("Plugin: {} -> Link: {}", name, link); - link + vec![ + ("game_version", format!("[\"{}\"]", game_version)), + ("loaders", format!("[\"{}\"]", loader)), + ("featured", true.to_string()), + ("version_type", channel), + ] } } }; - let modrinth_data: Vec = reqwest::get(link).await?.json().await?; + trace!("query: {:#?}", &query); + let client = reqwest::Client::builder() + .user_agent("TOwInOK/Minecraft-Dependency-Controller (TOwInOK@nothub.ru) TestPoligon") + .build()?; + + let modrinth_data: Vec = + client.get(&link).query(&query).send().await?.json().await?; let modrinth_data = match modrinth_data.first() { Some(e) => Ok(e), None => not_found_plugin_error!(name), }?; - Ok(modrinth_data - .files - .first() - .map(|x| { - ( - x.url.to_string(), - ChooseHash::SHA1(x.hashes.sha1.to_string()), - modrinth_data.id.to_owned(), - ) - }) - .unwrap()) + match modrinth_data.files.first().map(|x| { + ( + x.url.to_string(), + ChooseHash::SHA1(x.hashes.sha1.to_string()), + modrinth_data.id.to_owned(), + ) + }) { + Some(e) => Ok(e), + None => not_found_plugin_link_error!(name), + } } } diff --git a/src/settings/additions.rs b/src/settings/additions.rs index 15a6bfe..82c309f 100644 --- a/src/settings/additions.rs +++ b/src/settings/additions.rs @@ -10,15 +10,15 @@ pub struct Additions { key: Option, // duraction of delay between download intervals #[serde(default = "duraction_default")] - duraction: Option, + duraction: Option, } -fn duraction_default() -> Option { - Some(300f64) +fn duraction_default() -> Option { + Some(300) } impl Additions { - pub fn new(source: Option, key: Option, duraction: Option) -> Self { + pub fn new(source: Option, key: Option, duraction: Option) -> Self { Self { source, key, @@ -34,7 +34,7 @@ impl Additions { self.key.as_ref() } - pub fn duraction(&self) -> Option { + pub fn duraction(&self) -> Option { self.duraction } } diff --git a/src/settings/core.rs b/src/settings/core.rs index 7b1f0b0..7530df7 100644 --- a/src/settings/core.rs +++ b/src/settings/core.rs @@ -1,24 +1,29 @@ -use std::sync::Arc; -use std::time::Duration; +use crate::tr::load::Load; +use std::{sync::Arc, time::Duration}; use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; -use log::debug; +use lazy_static::lazy_static; +use log::{debug, trace}; use serde::{Deserialize, Serialize}; -use tokio::sync::Mutex; -use tokio::time::sleep; - -use crate::errors::error::Result; -use crate::lock::core::CoreMeta; -use crate::lock::Lock; -use crate::models::cores::folia::Folia; -use crate::models::cores::paper::Paper; -use crate::models::cores::purpur::Purpur; -use crate::models::cores::vanilla::Vanilla; -use crate::models::cores::velocity::Velocity; -use crate::models::cores::waterfall::Waterfall; -use crate::tr::hash::ChooseHash; -use crate::tr::model::core::ModelCore; -use crate::tr::{download::Download, save::Save}; +use tokio::{sync::Mutex, time::sleep}; + +use crate::{ + dictionary::pb_messages::PbMessages, + errors::error::Result, + lock::{core::CoreMeta, Lock}, + models::cores::{ + folia::Folia, paper::Paper, purpur::Purpur, vanilla::Vanilla, velocity::Velocity, + waterfall::Waterfall, + }, + pb, + tr::{ + delete::Delete, download::Download, hash::ChooseHash, model::core::ModelCore, save::Save, + }, +}; + +lazy_static! { + static ref DICT: PbMessages = PbMessages::load_sync().unwrap(); +} #[derive(Deserialize, Serialize, Debug, Default, PartialEq, Clone)] pub struct Core { @@ -26,6 +31,7 @@ pub struct Core { #[serde(default)] provider: Provider, // Версия ядра + // Change to Enum! #[serde(default = "version")] version: String, // Версия билда ядра @@ -91,31 +97,48 @@ impl Core { } /// Скачиваем `Core` и сохраняем его по стандартному пути. pub async fn download(&self, lock: Arc>, mpb: Arc) -> Result<()> { - let pb = mpb.add(ProgressBar::new_spinner()); - pb.set_style(ProgressStyle::with_template( - "Package:: {prefix:.blue} >>>{spinner:.green} {msg:.blue} > eta: {eta:.blue}", - )?); - pb.set_prefix(self.provider.as_str()); - // Check meta + let pb = pb!(mpb, self.provider.as_str()); let (link, hash, build) = self.get_link(&pb).await?; - + trace!("link: {}, hash: {}", &link, &hash); if let Some(e) = lock.lock().await.core().build() { - debug!("lock build: {} / build: {}", &e, &build); + trace!("lock build: {} / build: {}", &e, &build); if *e == build && (!self.force_update || self.freeze) { - pb.set_message("Does't need to update"); + pb.set_message(&DICT.doest_need_to_update); sleep(Duration::from_secs(1)).await; pb.finish_and_clear(); return Ok(()); } } + pb.set_message(&DICT.download_file); let file = Core::get_file(link, hash, &pb).await?; - pb.set_message("Saving file"); + debug!("file: => {} | got", self.provider().as_str()); + debug!("file: => {} | saving", self.provider().as_str()); + + pb.set_message(&DICT.delete_exist_version); + { + self.delete(lock.lock().await.core().path()).await; + } + + pb.set_message(&DICT.saving_file); Core::save_bytes(file, self.provider().as_str()).await?; - *lock.lock().await.core_mut() = self.clone().to_meta(build); - lock.lock().await.save().await?; - pb.set_message("Done"); - sleep(Duration::from_secs(1)).await; + + debug!("file: => {} | saved", self.provider().as_str()); + debug!("Data: => {} | start locking", self.provider().as_str()); + + pb.set_message(&DICT.write_to_lock); + { + let mut lock = lock.lock().await; + *lock.core_mut() = self.clone().to_meta(build); + lock.save().await?; + } + + debug!( + "Data: => {} | written into lock file", + self.provider().as_str() + ); + + pb.set_message(&DICT.done); pb.finish_and_clear(); Ok(()) } @@ -141,10 +164,10 @@ pub enum Provider { Vanilla, // done Paper, // done Folia, // done - Purpur, // in work, good api + Purpur, // done, good api Fabric, // in work, api with out hash //https://meta.fabricmc.net/v2/versions/game <- version check /v2/versions/intermediary give only stable - // or https://meta.fabricmc.net/v1/versions/game/1.14.4. Если нет версии, ответ пуст. + // or https://meta.fabricmc.net/v1/versions/game/1.14.4. If version is empty, response is empty. Forge, //no api NeoForge, //worst api Waterfall, // done @@ -171,3 +194,4 @@ impl Download for Core {} impl Save for Core { const PATH: &'static str = "./"; } +impl Delete for Core {} diff --git a/src/settings/extensions/plugin.rs b/src/settings/extensions/plugin.rs index 3a7860c..b3338a7 100644 --- a/src/settings/extensions/plugin.rs +++ b/src/settings/extensions/plugin.rs @@ -2,8 +2,12 @@ use serde::{Deserialize, Serialize}; use crate::errors::error::Result; use crate::models::extensions::modrinth::ModrinthData; +use crate::tr::download::Download; use crate::tr::hash::ChooseHash; use crate::tr::model::extension::ModelExtensions; +use crate::tr::save::Save; + +const PATH: &str = "./plugins/"; #[derive(Deserialize, Serialize, Debug, PartialEq, Default, Clone)] pub struct Plugin { @@ -86,3 +90,8 @@ impl Channels { } } } + +impl Download for Plugin {} +impl Save for Plugin { + const PATH: &'static str = PATH; +} diff --git a/src/settings/extensions/plugins.rs b/src/settings/extensions/plugins.rs index 369f2e7..c1ab3d9 100644 --- a/src/settings/extensions/plugins.rs +++ b/src/settings/extensions/plugins.rs @@ -1,22 +1,27 @@ +use crate::tr::load::Load; use std::collections::HashMap; use std::sync::Arc; -use std::time::Duration; use futures_util::future::join_all; use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; +use lazy_static::lazy_static; +use log::debug; use serde::{Deserialize, Serialize}; use tokio::sync::Mutex; use tokio::task::JoinHandle; -use tokio::time::sleep; +use super::plugin::Plugin; +use crate::dictionary::pb_messages::PbMessages; use crate::errors::error::Result; use crate::lock::ext::ExtensionMeta; use crate::lock::Lock; +use crate::pb; +use crate::tr::hash::ChooseHash; use crate::tr::{download::Download, save::Save}; -use super::plugin::Plugin; - -const PATH: &str = "./plugins/"; +lazy_static! { + static ref DICT: PbMessages = PbMessages::load_sync().unwrap(); +} #[derive(Deserialize, Serialize, Debug, Default, PartialEq)] pub struct Plugins(HashMap); @@ -37,68 +42,88 @@ impl Plugins { lock: Arc>, mpb: Arc, ) -> Result<()> { + let link_list = self.check_plugins(game_version, loader, mpb, &lock).await?; + let handler_list = make_handle_list(link_list, lock)?; + join_all(handler_list).await; + Ok(()) + } + + /// Check lock extensions with config extesions + async fn check_plugins( + &self, + game_version: &str, + loader: &str, + mpb: Arc, + lock: &Arc>, + ) -> Result> { let mut link_list = Vec::new(); - let mut handler_list: Vec>> = Vec::new(); - // Make link_list - // Check plugins in List - for (name, plugin) in self.0.clone() { + for (name, plugin) in self.0.iter() { + debug!("check extension: {}", &name); // Get link - let (link, hash, build) = plugin.get_link(&name, game_version, loader).await?; - // PB init - let pb = mpb.add(ProgressBar::new_spinner()); - // PB style - pb.set_style( - ProgressStyle::with_template( - "Package:: {prefix:.blue} >>>{spinner:.green} {msg:.blue} > eta: {eta:.blue}", - ) - .unwrap(), - ); - pb.set_prefix(name.clone()); + let (link, hash, build) = plugin.get_link(name, game_version, loader).await?; + debug!("got a link to the extesion: {}", &name); + let pb = pb!(mpb, name); + debug!("check meta: {}", &name); // Check meta - if let Some(plugin_meta) = lock.lock().await.plugins().get(&name) { + if let Some(plugin_meta) = lock.lock().await.plugins().get(name) { let local_build = plugin_meta.build(); // Need to download? if *local_build == build && !plugin.force_update() || plugin.freeze() { - pb.set_message("Does't need to update"); - sleep(Duration::from_secs(1)).await; + debug!("Does't need to update: {}", &name); + pb.set_message(&DICT.doest_need_to_update); pb.finish_and_clear(); continue; } } + debug!("add link to list: {}", &name); link_list.push((link, hash, build, name.to_owned(), pb)) } - // Make handler_list - for (link, hash, build, name, pb) in link_list { - let lock = Arc::clone(&lock); - - handler_list.push(tokio::spawn(async move { - // get file - let file = Plugin::get_file(link, hash, &pb).await?; - pb.set_message("Remove exist version"); - // delete prevision item - // get lock - lock.lock().await.remove_plugin(&name)?; - pb.set_message("Saving..."); - // save on disk - Plugin::save_bytes(file, name.as_str()).await?; - pb.set_message("Logging..."); - //save in lock - lock.lock().await.plugins_mut().insert(name.to_string(), { - ExtensionMeta::new(build, format!("{}{}.jar", PATH, name)) - }); - lock.lock().await.save().await?; - pb.set_message("Done"); - sleep(Duration::from_secs(1)).await; - pb.finish_and_clear(); - Ok(()) - })); - } - join_all(handler_list).await; - Ok(()) + Ok(link_list) } } -impl Download for Plugin {} -impl Save for Plugin { - const PATH: &'static str = PATH; +/// Create list with futures to download +fn make_handle_list( + link_list: Vec<(String, ChooseHash, String, String, ProgressBar)>, + lock: Arc>, +) -> Result>>> { + let mut handler_list: Vec>> = Vec::new(); + for (link, hash, build, name, pb) in link_list { + let lock = Arc::clone(&lock); + handler_list.push(tokio::spawn(async move { + // get file + let file = Plugin::get_file(link, hash, &pb).await?; + + debug!("Remove exist version of {}", &name); + { + pb.set_message(&DICT.delete_exist_version); + lock.lock().await.remove_plugin(&name).await; + } + debug!("Saving {}", &name); + + pb.set_message(&DICT.saving_file); + Plugin::save_bytes(file, &name).await?; + + debug!("Write data to lock file {}", &name); + + pb.set_message(&DICT.write_to_lock); + { + lock.lock() + .await + .plugins_mut() + .update(name.to_string(), { + ExtensionMeta::new(build, Plugin::PATH, &name) + }) + .await; + } + debug!("Save meta data to lock of {}", &name); + + lock.lock().await.save().await?; + pb.set_message(&DICT.done); + + pb.finish_and_clear(); + Ok(()) + })); + } + Ok(handler_list) } diff --git a/src/tr/delete.rs b/src/tr/delete.rs new file mode 100644 index 0000000..29747f6 --- /dev/null +++ b/src/tr/delete.rs @@ -0,0 +1,18 @@ +use async_trait::async_trait; +use log::warn; +use tokio::fs; + +#[async_trait] +pub trait Delete { + /// Delete file from the file system + async fn delete(&self, path: &str) { + if !path.is_empty() { + match fs::remove_file(path).await { + Ok(_) => {} + Err(e) => { + warn!("IO error: {}, with path: {}", e, path) + } + }; + } + } +} diff --git a/src/tr/download.rs b/src/tr/download.rs index 7a2b135..fa3ef36 100644 --- a/src/tr/download.rs +++ b/src/tr/download.rs @@ -1,38 +1,61 @@ +use super::hash::ChooseHash; use crate::errors::error::Result; +use async_trait::async_trait; use bytes::{Bytes, BytesMut}; use futures_util::StreamExt; use indicatif::ProgressBar; -use super::hash::ChooseHash; +use crate::dictionary::pb_messages::PbMessages; +use crate::tr::load::Load; +use lazy_static::lazy_static; + +lazy_static! { + static ref DICT: PbMessages = PbMessages::load_sync().unwrap(); +} + +#[async_trait] pub trait Download { - fn get_file( - link: String, - hash: ChooseHash, - pb: &ProgressBar, - ) -> impl std::future::Future> + Send { - async move { - // make reqwest - let response = reqwest::get(link).await?; - // know size of file - let size = response.content_length().unwrap_or(0); - pb.set_length(size); + async fn get_file(link: String, hash: ChooseHash, pb: &ProgressBar) -> Result { + // make reqwest + let response = reqwest::get(link).await?; + // know size of file + let size = response.content_length().unwrap_or(0); + pb.set_length(size); - pb.set_message("Download..."); + pb.set_message(&DICT.download_file); - let mut size_upload = 0_u64; - let mut content = BytesMut::new(); - let mut a = response.bytes_stream(); - while let Some(chunk) = a.next().await { - let chunk = chunk?; - size_upload += chunk.len() as u64; - pb.set_position(size_upload); - content.extend_from_slice(&chunk) - } - pb.set_message("Calculate hash..."); - hash.calculate_hash(&*content).await?; - // End - pb.set_message("Downloaded!"); - Ok(content.freeze()) + let mut size_upload = 0_u64; + let mut content = BytesMut::new(); + let mut a = response.bytes_stream(); + while let Some(chunk) = a.next().await { + let chunk = chunk?; + size_upload += chunk.len() as u64; + pb.set_position(size_upload); + content.extend_from_slice(&chunk) } + pb.set_message(&DICT.calculate_hash); + hash.calculate_hash(&*content).await?; + // End + pb.set_message(&DICT.file_downloaded); + Ok(content.freeze()) } } + +/// Make progress bar with template +/// +/// ` Package:: {PackageName} >>>{spinner} {msg} > eta: {eta} ` +#[macro_export] +macro_rules! pb { + ($mpb:expr, $name:expr) => {{ + let name = $name.to_string(); + let pb = $mpb.add(ProgressBar::new_spinner()); + pb.set_style( + ProgressStyle::with_template( + "Package:: {prefix:.blue} >>>{spinner:.green} {msg:.blue} > eta: {eta:.blue}", + ) + .unwrap(), + ); + pb.set_prefix(name.clone()); + pb + }}; +} diff --git a/src/tr/hash.rs b/src/tr/hash.rs index 1bc3d65..cbdc635 100644 --- a/src/tr/hash.rs +++ b/src/tr/hash.rs @@ -22,7 +22,7 @@ impl ChooseHash { match self { ChooseHash::SHA1(e) => { let mut hashed = ::new(); - let mut buffer = Vec::::new(); + let mut buffer = [0; 32]; while let Ok(n) = reader.read(&mut buffer).await { if n == 0 { break; @@ -33,12 +33,15 @@ impl ChooseHash { if e.eq(&format!("{:x}", result)) { Ok(()) } else { - Err(Error::CompareHash(CompareHashError::HashNotCompare())) + Err(Error::CompareHash(CompareHashError::HashNotCompare( + e.to_owned(), + format!("{:x}", result), + ))) } } ChooseHash::SHA256(e) => { let mut hashed = ::new(); - let mut buffer = Vec::::new(); + let mut buffer = [0; 32]; while let Ok(n) = reader.read(&mut buffer).await { if n == 0 { break; @@ -49,12 +52,15 @@ impl ChooseHash { if e.eq(&format!("{:x}", result)) { Ok(()) } else { - Err(Error::CompareHash(CompareHashError::HashNotCompare())) + Err(Error::CompareHash(CompareHashError::HashNotCompare( + e.to_owned(), + format!("{:x}", result), + ))) } } ChooseHash::MD5(e) => { let mut hashed = ::new(); - let mut buffer = Vec::::new(); + let mut buffer = [0; 32]; while let Ok(n) = reader.read(&mut buffer).await { if n == 0 { break; @@ -65,7 +71,10 @@ impl ChooseHash { if e.eq(&format!("{:x}", result)) { Ok(()) } else { - Err(Error::CompareHash(CompareHashError::HashNotCompare())) + Err(Error::CompareHash(CompareHashError::HashNotCompare( + e.to_owned(), + format!("{:x}", result), + ))) } } ChooseHash::None => Ok(()), diff --git a/src/tr/load.rs b/src/tr/load.rs index 52a83eb..53c4075 100644 --- a/src/tr/load.rs +++ b/src/tr/load.rs @@ -1,20 +1,36 @@ use crate::errors::error::Result; +use async_trait::async_trait; +use log::debug; use serde::Deserialize; -use tokio::fs; +use tokio::fs::{self}; /// Загружаем с диска нужную нам структуру +#[async_trait] pub trait Load { const PATH: &'static str; - fn load() -> impl std::future::Future> + Send + + async fn load() -> Result where for<'de> Self: Deserialize<'de>, { - async move { - // Читаем с диска - let file = fs::read_to_string(Self::PATH).await?; - // Преобразуем в структуру - let item: Self = toml::from_str(&file)?; - // Выдача результата - Ok(item) - } + // Читаем с диска + debug!("Load file: {:#?}", Self::PATH); + let file = fs::read_to_string(Self::PATH).await?; + // Преобразуем в структуру + let item: Self = toml::from_str(&file)?; + // Выдача результата + Ok(item) + } + fn load_sync() -> Result + where + for<'de> Self: Deserialize<'de>, + { + // Читаем с диска + debug!("Load file: {:#?}", Self::PATH); + + let file = std::fs::read_to_string(Self::PATH)?; + // Преобразуем в структуру + let item: Self = toml::from_str(&file)?; + // Выдача результата + Ok(item) } } diff --git a/src/tr/mod.rs b/src/tr/mod.rs index 421c002..df944d2 100644 --- a/src/tr/mod.rs +++ b/src/tr/mod.rs @@ -1,3 +1,4 @@ +pub mod delete; pub mod download; pub mod hash; pub mod load; diff --git a/src/tr/save.rs b/src/tr/save.rs index 57fc1aa..80c33f6 100644 --- a/src/tr/save.rs +++ b/src/tr/save.rs @@ -1,57 +1,51 @@ use crate::errors::error::{Error, Result}; use crate::not_found_path; +use async_trait::async_trait; use bytes::Bytes; +use log::debug; use std::path::Path; use tokio::fs::File; use tokio::io::AsyncWriteExt; /// Сохраняем структуру на диск +#[async_trait] pub trait Save { const PATH: &'static str; // Save data into file. - fn save(&self) -> impl std::future::Future> + Send + async fn save(&self) -> Result<()> where Self: serde::ser::Serialize + Sync, { - async move { - { - // Сериализуем в понятный человеку томл - let toml_content = toml::to_string_pretty(&self)?; + // Сериализуем в понятный человеку томл + let toml_content = toml::to_string_pretty(&self)?; + debug!("Save content: {}", Self::PATH); + // Откроем для записи + let mut file = File::create(Self::PATH).await?; - // Откроем для записи - let mut file = File::create(Self::PATH).await?; + // Запишем файл + file.write_all(toml_content.as_bytes()).await?; - // Запишем файл - file.write_all(toml_content.as_bytes()).await?; - - Ok(()) - } - } + Ok(()) } // Create file by data - fn save_bytes( - bytes: Bytes, - name: &str, - ) -> impl std::future::Future> + Send { - async move { - { - // Конвертируем &str в Path - let path_to_dir = Path::new(Self::PATH); - // Проверить путь на исправность - if !path_to_dir.exists() { - return not_found_path!(Self::PATH); - } - // Добавляем имя к пути - let path_to_file = path_to_dir.join(format!("{}.jar", name)); + async fn save_bytes(bytes: Bytes, name: &str) -> Result<()> { + // Конвертируем &str в Path + let path_to_dir = Path::new(Self::PATH); + // Проверить путь на исправность + if !path_to_dir.exists() { + return not_found_path!(Self::PATH); + } + debug!("path to dir: {:#?}", path_to_dir.to_str()); + // Добавляем имя к пути + let path_to_file = path_to_dir.join(format!("{}.jar", name)); - // Откроем для записи - let mut file = File::create(path_to_file).await?; + debug!("path to file: {:#?}", path_to_file.to_str()); + // Откроем для записи + let mut file = File::create(path_to_file).await?; - // Запишем файл - file.write_all(&bytes).await?; + // Запишем файл + file.write_all(&bytes).await?; - Ok(()) - } - } + Ok(()) } }