aurora-modules 0.1.0

Git, filesystem, system, network, archive, docker, unix, crypto, calculator, QR, color, timer, notes, clipboard, and text processing modules
Documentation
use aurora_core::{AuroraResult, Pipeline, Value};
use std::process::Command;
use std::fs;
use walkdir::WalkDir;

pub fn unix_ps() -> AuroraResult<Pipeline> {
    let output = Command::new("ps")
        .args(["aux"])
        .output()
        .map_err(|e| aurora_core::AuroraError::ModuleError(
            format!("ps failed: {}", e)
        ))?;

    let stdout = String::from_utf8_lossy(&output.stdout);
    let mut rows: Vec<Vec<Value>> = Vec::new();

    for (i, line) in stdout.lines().enumerate() {
        if i == 0 || line.trim().is_empty() { continue; }
        let parts: Vec<&str> = line.split_whitespace().collect();
        if parts.len() >= 11 {
            rows.push(vec![
                Value::String(parts[0].into()),
                Value::String(parts[1].into()),
                Value::String(parts[2].into()),
                Value::String(parts[3].into()),
                Value::String(parts[10].into()),
            ]);
        }
    }

    Ok(Pipeline::table(
        vec!["user".into(), "pid".into(), "cpu%".into(), "mem%".into(), "command".into()],
        rows,
    ))
}

pub fn unix_df(human: bool) -> AuroraResult<Pipeline> {
    let mut cmd = Command::new("df");
    if human {
        cmd.arg("-h");
    }

    let output = cmd.output()
        .map_err(|e| aurora_core::AuroraError::ModuleError(
            format!("df failed: {}", e)
        ))?;

    let stdout = String::from_utf8_lossy(&output.stdout);
    let mut rows: Vec<Vec<Value>> = Vec::new();

    for (i, line) in stdout.lines().enumerate() {
        if i == 0 || line.trim().is_empty() { continue; }
        let parts: Vec<&str> = line.split_whitespace().collect();
        if parts.len() >= 6 {
            rows.push(vec![
                Value::String(parts[0].into()),
                Value::String(parts[1].into()),
                Value::String(parts[2].into()),
                Value::String(parts[3].into()),
                Value::String(parts[4].into()),
                Value::String(parts[5].into()),
            ]);
        }
    }

    Ok(Pipeline::table(
        vec!["filesystem".into(), "size".into(), "used".into(), "avail".into(), "use%".into(), "mounted".into()],
        rows,
    ))
}

pub fn unix_du(path: &str) -> AuroraResult<Pipeline> {
    let mut rows: Vec<Vec<Value>> = Vec::new();

    for entry in WalkDir::new(path).into_iter().filter_map(|e| e.ok()) {
        if entry.file_type().is_dir() {
            let p = entry.path().to_string_lossy().to_string();
            let mut size: i64 = 0;
            if let Ok(dir) = fs::read_dir(entry.path()) {
                for sub in dir.flatten() {
                    if let Ok(meta) = sub.metadata() {
                        size += meta.len() as i64;
                    }
                }
            }
            rows.push(vec![
                Value::String(p),
                Value::Int(size),
            ]);
        }
    }

    Ok(Pipeline::table(
        vec!["path".into(), "size_bytes".into()],
        rows,
    ))
}

pub fn unix_uptime() -> AuroraResult<Pipeline> {
    let content = fs::read_to_string("/proc/uptime")
        .ok();

    if let Some(uptime_str) = content {
        if let Some(secs) = uptime_str.split(' ').next() {
            let secs = secs.trim();
            let secs_f: f64 = secs.parse().unwrap_or(0.0);
            let days = (secs_f / 86400.0) as i64;
            let hours = ((secs_f % 86400.0) / 3600.0) as i64;
            let minutes = ((secs_f % 3600.0) / 60.0) as i64;

            return Ok(Pipeline::table(
                vec!["uptime_seconds".into(), "days".into(), "hours".into(), "minutes".into()],
                vec![vec![
                    Value::Float(secs_f),
                    Value::Int(days),
                    Value::Int(hours),
                    Value::Int(minutes),
                ]],
            ));
        }
    }

    let output = Command::new("uptime")
        .output()
        .ok();
    if let Some(out) = output {
        let stdout = String::from_utf8_lossy(&out.stdout);
        return Ok(Pipeline::table(
            vec!["uptime".into()],
            vec![vec![Value::String(stdout.trim().into())]],
        ));
    }

    Ok(Pipeline::table(
        vec!["uptime".into()],
        vec![vec![Value::String("unknown".into())]],
    ))
}

pub fn unix_env() -> AuroraResult<Pipeline> {
    let mut rows: Vec<Vec<Value>> = Vec::new();

    for (key, value) in std::env::vars() {
        rows.push(vec![
            Value::String(key),
            Value::String(value),
        ]);
    }

    Ok(Pipeline::table(
        vec!["key".into(), "value".into()],
        rows,
    ))
}

pub fn unix_uname() -> AuroraResult<Pipeline> {
    let output = Command::new("uname")
        .arg("-a")
        .output()
        .map_err(|e| aurora_core::AuroraError::ModuleError(
            format!("uname failed: {}", e)
        ))?;

    let stdout = String::from_utf8_lossy(&output.stdout);
    let parts: Vec<&str> = stdout.trim().split_whitespace().collect();

    let kernel = parts.get(0).copied().unwrap_or("");
    let hostname = parts.get(1).copied().unwrap_or("");
    let kernel_release = parts.get(2).copied().unwrap_or("");
    let kernel_version = parts.get(3).copied().unwrap_or("");
    let arch = if parts.len() > 11 { parts[11] } else { parts.last().copied().unwrap_or("") };

    Ok(Pipeline::table(
        vec!["kernel".into(), "hostname".into(), "release".into(), "version".into(), "arch".into()],
        vec![vec![
            Value::String(kernel.into()),
            Value::String(hostname.into()),
            Value::String(kernel_release.into()),
            Value::String(kernel_version.into()),
            Value::String(arch.into()),
        ]],
    ))
}