rootftp 0.3.1

A simple FTP server tool that allows you to play with files. Multiple users can share their files with each other. You can also build custom plugins see examples for more info.
Documentation
mod auth;
mod config;
mod constants;
mod helpers;
mod listeners;
mod plugin_handler;
mod system;

use clap::Parser;
use config::Config;
use constants::SimpleAuthenticator;
use helpers::server_handler::{daemonize, start_server, stop_server};
use local_ip_address::local_ip;
use system::cli::{Cli, Commands};
use system::init;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let cli = Cli::parse();

    if matches!(cli.command, Commands::Start { daemon: true }) {
        daemonize()?;
    }

    let rt = tokio::runtime::Builder::new_current_thread()
        .enable_all()
        .build()?;
    rt.block_on(run(cli))
}

async fn run(cli: Cli) -> Result<(), Box<dyn std::error::Error>> {
    let mut config = Config::load();
    let path = config.root_dir.join("credentials.json");
    let auth = SimpleAuthenticator::new(path.clone());

    let ip = local_ip().unwrap_or_else(|e| {
        eprintln!(
            "[Warning]: could not detect local IP ({}), falling back to 0.0.0.0",
            e
        );
        std::net::IpAddr::V4(std::net::Ipv4Addr::new(0, 0, 0, 0))
    });
    let addr = format!("{}:{}", ip, 2121);

    match cli.command {
        Commands::Start { daemon } => {
            println!("Starting FTP server...");
            start_server(daemon, auth, config.root_dir.clone(), addr.clone()).await?;
        }
        Commands::Stop => {
            stop_server().await;
            println!("FTP server stopped...");
        }
        Commands::Setdir { _path } => {
            config.root_dir = _path;
            config.save();
            println!("Root directory set to: {}", config.root_dir.display());
        }
        Commands::Status => {
            helpers::command_helper::status().await;
        }
        Commands::Loadplugin { _path } => {
            helpers::load_plugin::load_plugin(&_path);
        }
        Commands::Fetch => {
            helpers::plugin_library_handler::load_plugins(true).await?;
        }
        Commands::Install { plugin_name } => {
            helpers::plugin_library_handler::install_plugin(&plugin_name).await?;
        }
        Commands::List => {
            helpers::plugin_library_handler::list_plugins().await;
        }
    }
    Ok(())
}