ice 0.4.0

A simple CTF tool store
Documentation
use anyhow::{anyhow, Context, Result};
use regex::Regex;
use std::path::Path;
use std::sync::LazyLock;

fn get_input(input: &str) -> Result<String> {
    if Path::new(input).exists() {
        std::fs::read_to_string(input).context("Failed to read file")
    } else {
        Ok(input.to_string())
    }
}

static EMAIL_RE: LazyLock<Regex> = LazyLock::new(|| {
    Regex::new(r"[a-z0-9_+][a-z0-9_+.]*[a-z0-9_+]?@[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6}")
        .unwrap()
});

static PHONE_RE: LazyLock<Regex> = LazyLock::new(|| {
    Regex::new(r"[\.\-)( ]*([0-9]{3})[\.\-)( ]*([0-9]{3})[\.\-)( ]*([0-9]{4})").unwrap()
});

static IP_RE: LazyLock<Regex> =
    LazyLock::new(|| Regex::new(r"((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}").unwrap());

static MAC_RE: LazyLock<Regex> =
    LazyLock::new(|| Regex::new(r"(?i)([0-9a-f]{2}[:-]){5}[0-9a-f]{2}").unwrap());

static FLAG_RE: LazyLock<Regex> =
    LazyLock::new(|| Regex::new(r"(?i)\b[a-z0-9_]+\{[^}\n]{2,200}\}").unwrap());

fn emails(content: &str) -> Vec<String> {
    EMAIL_RE
        .captures_iter(content)
        .map(|i| i[0].to_string())
        .collect()
}

fn phones(content: &str) -> Vec<String> {
    PHONE_RE
        .captures_iter(content)
        .map(|i| i[0].to_string())
        .collect()
}

fn ips(content: &str) -> Vec<String> {
    IP_RE
        .captures_iter(content)
        .map(|i| i[0].to_string())
        .collect()
}

fn macs(content: &str) -> Vec<String> {
    MAC_RE
        .captures_iter(content)
        .map(|i| i[0].to_string())
        .collect()
}

fn flags(content: &str) -> Vec<String> {
    FLAG_RE
        .captures_iter(content)
        .map(|i| i[0].to_string())
        .collect()
}

pub fn extractor(xtype: &str, input: &str) -> Result<String> {
    let content = get_input(input)?;
    let matches = match xtype {
        "email" => emails(&content),
        "phone" => phones(&content),
        "ip" => ips(&content),
        "mac" => macs(&content),
        "flag" => flags(&content),
        _ => return Err(anyhow!("Unknown extract type: {}", xtype)),
    };

    Ok(matches.join("\n"))
}