Checks if folder is a destination folder

This commit is contained in:
2025-01-24 00:12:25 +01:00
parent f04208669b
commit 5dc724035e

View File

@@ -1,19 +1,19 @@
use clap::{arg, command, value_parser}; use clap::{arg, command, value_parser};
use ratatui::crossterm::event::{self, Event, KeyCode, KeyModifiers};
use ratatui::layout::{Constraint::Max, Layout}; use ratatui::layout::{Constraint::Max, Layout};
use ratatui::text::Line; use ratatui::text::Line;
use ratatui::widgets::{Block, Paragraph, Wrap}; use ratatui::widgets::{Block, Paragraph, Wrap};
use ratatui::Frame; use ratatui::Frame;
use ratatui::crossterm::event::{self, Event, KeyCode, KeyModifiers};
use serde::Deserialize; use serde::Deserialize;
use serde_json::from_reader; use serde_json::from_reader;
use std::cmp::PartialEq; use std::cmp::PartialEq;
use std::fs::{copy, File}; use std::fs::{copy, File};
use std::path::PathBuf; use std::path::PathBuf;
use std::process::exit;
use std::sync::mpsc::{sync_channel, Receiver, SyncSender}; use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::thread::{sleep, spawn}; use std::thread::{sleep, spawn};
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};
use std::process::exit;
const VIDEO: [&str; 8] = ["mp4", "webm", "mov", "avi", "wmv", "flv", "mkv", "qt"]; const VIDEO: [&str; 8] = ["mp4", "webm", "mov", "avi", "wmv", "flv", "mkv", "qt"];
const AUDIO: [&str; 4] = ["mp3", "wav", "ogg", "opus"]; const AUDIO: [&str; 4] = ["mp3", "wav", "ogg", "opus"];
@@ -25,7 +25,7 @@ enum Progress {
Done, Done,
} }
#[derive(Deserialize)] #[derive(Deserialize, Clone)]
struct Config { struct Config {
video: PathBuf, video: PathBuf,
audio: PathBuf, audio: PathBuf,
@@ -33,10 +33,20 @@ struct Config {
document: PathBuf, document: PathBuf,
} }
impl Config {
fn contains(&self, path: &PathBuf) -> bool {
if &self.video == path || &self.audio == path || &self.image == path || &self.document == path {
true
} else {
false
}
}
}
struct Status { struct Status {
progress: Progress, progress: Progress,
path: PathBuf, path: PathBuf,
message: String message: String,
} }
impl Default for Status { impl Default for Status {
@@ -44,7 +54,7 @@ impl Default for Status {
Status { Status {
progress: Progress::Working, progress: Progress::Working,
path: PathBuf::new(), path: PathBuf::new(),
message: String::new() message: String::new(),
} }
} }
} }
@@ -57,20 +67,20 @@ struct FileMover {
} }
impl FileFinder { impl FileFinder {
fn run(self, folder: &PathBuf) -> Arc<Mutex<Status>> { fn run(self, folder: &PathBuf, config: Config) -> Arc<Mutex<Status>> {
let folder = folder.clone(); let folder = folder.clone();
let status = Arc::new(Mutex::new(Status::default())); let status = Arc::new(Mutex::new(Status::default()));
let status_clone = status.clone(); let status_clone = status.clone();
spawn(move || { spawn(move || {
if folder.is_dir() { if folder.is_dir() {
self.read_folder(folder, status_clone.clone()); self.read_folder(folder, status_clone.clone(), &config);
} }
status_clone.lock().unwrap().progress = Progress::Done; status_clone.lock().unwrap().progress = Progress::Done;
}); });
status status
} }
fn read_folder(&self, folder: PathBuf, status: Arc<Mutex<Status>>) { fn read_folder(&self, folder: PathBuf, status: Arc<Mutex<Status>>, config: &Config) {
let mut now = SystemTime::now(); let mut now = SystemTime::now();
if let Ok(dir_iter) = folder.read_dir() { if let Ok(dir_iter) = folder.read_dir() {
for entry in dir_iter { for entry in dir_iter {
@@ -85,7 +95,9 @@ impl FileFinder {
} }
} }
if path.is_dir() { if path.is_dir() {
self.read_folder(path, status.clone()); if !config.contains(&path) {
self.read_folder(path, status.clone(), config);
}
} else if path.is_file() { } else if path.is_file() {
self.sender self.sender
.send(path) .send(path)
@@ -101,12 +113,10 @@ impl FileFinder {
} }
impl FileMover { impl FileMover {
fn run(self, config: &PathBuf) -> Arc<Mutex<Status>> { fn run(self, config: Config) -> Arc<Mutex<Status>> {
let mut now = SystemTime::now(); let mut now = SystemTime::now();
let status = Arc::new(Mutex::new(Status::default())); let status = Arc::new(Mutex::new(Status::default()));
let status_clone = status.clone(); let status_clone = status.clone();
let config_file = File::open(config).expect("Could not open config file");
let config: Config = from_reader(config_file).expect("Could not parse config file");
spawn(move || { spawn(move || {
for file in self.receiver.iter() { for file in self.receiver.iter() {
if let Ok(elapsed) = now.elapsed() { if let Ok(elapsed) = now.elapsed() {
@@ -132,12 +142,18 @@ impl FileMover {
if let Some(destination) = destination { if let Some(destination) = destination {
let result = copy(&file, &destination); let result = copy(&file, &destination);
if result.is_err() { if result.is_err() {
status_clone.lock().unwrap().message = format!("Error: Could not copy file {:?}\n{}", file.file_name().unwrap(), result.err().unwrap()); status_clone.lock().unwrap().message = format!(
"Error: Could not copy file {:?}\n{}",
file.file_name().unwrap(),
result.err().unwrap()
);
} else { } else {
status_clone.lock().unwrap().message = format!("Successfully copied file {:?}", file.file_name().unwrap()); status_clone.lock().unwrap().message = format!(
"Successfully copied file {:?}",
file.file_name().unwrap()
);
} }
} }
} }
} }
sleep(Duration::from_millis(100)); sleep(Duration::from_millis(100));
@@ -177,7 +193,10 @@ fn main() {
let finder = FileFinder::new(sender); let finder = FileFinder::new(sender);
let mover = FileMover::new(receiver); let mover = FileMover::new(receiver);
let finder_status = finder.run(folder); let config_file = File::open(config).expect("Could not open config file");
let config: Config = from_reader(config_file).expect("Could not parse config file");
let finder_status = finder.run(folder, config.clone());
let mover_status = mover.run(config); let mover_status = mover.run(config);
while finder_status.lock().unwrap().progress == Progress::Working while finder_status.lock().unwrap().progress == Progress::Working
@@ -187,20 +206,24 @@ fn main() {
.draw(|frame: &mut Frame| { .draw(|frame: &mut Frame| {
let layout = Layout::vertical([Max(5), Max(5)]); let layout = Layout::vertical([Max(5), Max(5)]);
let [reader_area, mover_area] = layout.areas(frame.area()); let [reader_area, mover_area] = layout.areas(frame.area());
let reader = vec![Line::from(format!( let reader = vec![
"Discovered: {:?}", Line::from(format!(
finder_status.lock().unwrap().path "Discovered: {:?}",
)), finder_status.lock().unwrap().path
Line::from(finder_status.lock().unwrap().message.clone())]; )),
Line::from(finder_status.lock().unwrap().message.clone()),
];
let reader_paragraph = Paragraph::new(reader) let reader_paragraph = Paragraph::new(reader)
.block(Block::bordered().title("FileFinder status")) .block(Block::bordered().title("FileFinder status"))
.centered() .centered()
.wrap(Wrap { trim: true }); .wrap(Wrap { trim: true });
let mover = vec![Line::from(format!( let mover = vec![
"Current file: {:?}", Line::from(format!(
mover_status.lock().unwrap().path "Current file: {:?}",
)), mover_status.lock().unwrap().path
Line::from(mover_status.lock().unwrap().message.clone())]; )),
Line::from(mover_status.lock().unwrap().message.clone()),
];
let mover_paragraph = Paragraph::new(mover) let mover_paragraph = Paragraph::new(mover)
.block(Block::bordered().title("FileMover status")) .block(Block::bordered().title("FileMover status"))
.centered() .centered()
@@ -212,14 +235,15 @@ fn main() {
if event::poll(Duration::from_millis(100)).unwrap() { if event::poll(Duration::from_millis(100)).unwrap() {
let ev = event::read().unwrap(); let ev = event::read().unwrap();
match ev { match ev {
Event::Key(key) if key.code == KeyCode::Char('c') && key.modifiers == KeyModifiers::CONTROL => { Event::Key(key)
if key.code == KeyCode::Char('c') && key.modifiers == KeyModifiers::CONTROL =>
{
ratatui::restore(); ratatui::restore();
exit(0); exit(0);
} }
_ => {} _ => {}
} }
} }
} }
ratatui::restore(); ratatui::restore();