Checks if folder is a destination folder
This commit is contained in:
80
src/main.rs
80
src/main.rs
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user