feat: trace-level matching, health watcher/worker status, timezone config
This commit is contained in:
@@ -17,42 +17,84 @@ mod tests {
|
||||
#[test]
|
||||
fn test_detect_category_image() {
|
||||
assert_eq!(detect_category(Path::new("photo.jpg")), FileCategory::Image);
|
||||
assert_eq!(detect_category(Path::new("photo.jpeg")), FileCategory::Image);
|
||||
assert_eq!(
|
||||
detect_category(Path::new("photo.jpeg")),
|
||||
FileCategory::Image
|
||||
);
|
||||
assert_eq!(detect_category(Path::new("photo.png")), FileCategory::Image);
|
||||
assert_eq!(detect_category(Path::new("photo.svg")), FileCategory::Image);
|
||||
assert_eq!(detect_category(Path::new("photo.webp")), FileCategory::Image);
|
||||
assert_eq!(
|
||||
detect_category(Path::new("photo.webp")),
|
||||
FileCategory::Image
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_detect_category_document() {
|
||||
assert_eq!(detect_category(Path::new("doc.pdf")), FileCategory::Document);
|
||||
assert_eq!(detect_category(Path::new("doc.docx")), FileCategory::Document);
|
||||
assert_eq!(detect_category(Path::new("doc.pages")), FileCategory::Document);
|
||||
assert_eq!(detect_category(Path::new("doc.txt")), FileCategory::Document);
|
||||
assert_eq!(
|
||||
detect_category(Path::new("doc.pdf")),
|
||||
FileCategory::Document
|
||||
);
|
||||
assert_eq!(
|
||||
detect_category(Path::new("doc.docx")),
|
||||
FileCategory::Document
|
||||
);
|
||||
assert_eq!(
|
||||
detect_category(Path::new("doc.pages")),
|
||||
FileCategory::Document
|
||||
);
|
||||
assert_eq!(
|
||||
detect_category(Path::new("doc.txt")),
|
||||
FileCategory::Document
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_detect_category_spreadsheet() {
|
||||
assert_eq!(detect_category(Path::new("data.xlsx")), FileCategory::Spreadsheet);
|
||||
assert_eq!(detect_category(Path::new("data.csv")), FileCategory::Spreadsheet);
|
||||
assert_eq!(detect_category(Path::new("data.numbers")), FileCategory::Spreadsheet);
|
||||
assert_eq!(
|
||||
detect_category(Path::new("data.xlsx")),
|
||||
FileCategory::Spreadsheet
|
||||
);
|
||||
assert_eq!(
|
||||
detect_category(Path::new("data.csv")),
|
||||
FileCategory::Spreadsheet
|
||||
);
|
||||
assert_eq!(
|
||||
detect_category(Path::new("data.numbers")),
|
||||
FileCategory::Spreadsheet
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_detect_category_presentation() {
|
||||
assert_eq!(detect_category(Path::new("deck.pptx")), FileCategory::Presentation);
|
||||
assert_eq!(detect_category(Path::new("deck.key")), FileCategory::Presentation);
|
||||
assert_eq!(
|
||||
detect_category(Path::new("deck.pptx")),
|
||||
FileCategory::Presentation
|
||||
);
|
||||
assert_eq!(
|
||||
detect_category(Path::new("deck.key")),
|
||||
FileCategory::Presentation
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_detect_category_archive() {
|
||||
assert_eq!(detect_category(Path::new("files.zip")), FileCategory::Archive);
|
||||
assert_eq!(detect_category(Path::new("files.tar.gz")), FileCategory::Archive);
|
||||
assert_eq!(
|
||||
detect_category(Path::new("files.zip")),
|
||||
FileCategory::Archive
|
||||
);
|
||||
assert_eq!(
|
||||
detect_category(Path::new("files.tar.gz")),
|
||||
FileCategory::Archive
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_detect_category_unknown() {
|
||||
assert_eq!(detect_category(Path::new("file.xyz")), FileCategory::Unknown);
|
||||
assert_eq!(
|
||||
detect_category(Path::new("file.xyz")),
|
||||
FileCategory::Unknown
|
||||
);
|
||||
assert_eq!(detect_category(Path::new("file")), FileCategory::Unknown);
|
||||
}
|
||||
|
||||
@@ -84,13 +126,18 @@ pub enum FileCategory {
|
||||
|
||||
/// Detect file category from path extension
|
||||
pub fn detect_category(path: &Path) -> FileCategory {
|
||||
let ext = path.extension()
|
||||
let ext = path
|
||||
.extension()
|
||||
.and_then(|e| e.to_str())
|
||||
.map(|e| e.to_lowercase());
|
||||
match ext.as_deref() {
|
||||
Some("mp4" | "mov" | "mkv" | "avi" | "webm" | "m4v" | "mpeg") => FileCategory::Video,
|
||||
Some("jpg" | "jpeg" | "png" | "gif" | "bmp" | "webp" | "svg" | "heic" | "tiff") => FileCategory::Image,
|
||||
Some("pdf" | "doc" | "docx" | "odt" | "pages" | "rtf" | "txt" | "md" | "rst") => FileCategory::Document,
|
||||
Some("jpg" | "jpeg" | "png" | "gif" | "bmp" | "webp" | "svg" | "heic" | "tiff") => {
|
||||
FileCategory::Image
|
||||
}
|
||||
Some("pdf" | "doc" | "docx" | "odt" | "pages" | "rtf" | "txt" | "md" | "rst") => {
|
||||
FileCategory::Document
|
||||
}
|
||||
Some("xls" | "xlsx" | "csv" | "ods" | "numbers") => FileCategory::Spreadsheet,
|
||||
Some("ppt" | "pptx" | "odp" | "key") => FileCategory::Presentation,
|
||||
Some("zip" | "tar" | "gz" | "tgz" | "7z" | "rar") => FileCategory::Archive,
|
||||
@@ -102,16 +149,20 @@ pub fn detect_category(path: &Path) -> FileCategory {
|
||||
pub fn base_format_info(path: &Path) -> serde_json::Value {
|
||||
let meta = std::fs::metadata(path).ok();
|
||||
let size = meta.as_ref().map(|m| m.len()).unwrap_or(0);
|
||||
let mtime = meta.as_ref()
|
||||
let mtime = meta
|
||||
.as_ref()
|
||||
.and_then(|m| m.modified().ok())
|
||||
.and_then(|t| {
|
||||
let secs = t.duration_since(SystemTime::UNIX_EPOCH).ok()?.as_secs() as i64;
|
||||
chrono::DateTime::from_timestamp(secs, 0)
|
||||
.map(|dt| dt.to_rfc3339())
|
||||
chrono::DateTime::from_timestamp(secs, 0).map(|dt| dt.to_rfc3339())
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let fname = path.to_string_lossy().to_string();
|
||||
let ext = path.extension().and_then(|e| e.to_str()).unwrap_or("").to_lowercase();
|
||||
let ext = path
|
||||
.extension()
|
||||
.and_then(|e| e.to_str())
|
||||
.unwrap_or("")
|
||||
.to_lowercase();
|
||||
let cat = detect_category(path);
|
||||
let file_type = match cat {
|
||||
FileCategory::Video => "video",
|
||||
@@ -150,7 +201,13 @@ fn ffprobe_probe(path: &Path, format_base: serde_json::Value) -> serde_json::Val
|
||||
}
|
||||
|
||||
/// Run Python probe for document/spreadsheet/presentation files
|
||||
fn python_probe(path: &Path, category: &FileCategory, scripts_dir: &str, python_path: &str, format_base: serde_json::Value) -> serde_json::Value {
|
||||
fn python_probe(
|
||||
path: &Path,
|
||||
category: &FileCategory,
|
||||
scripts_dir: &str,
|
||||
python_path: &str,
|
||||
format_base: serde_json::Value,
|
||||
) -> serde_json::Value {
|
||||
let script = format!("{}/probe_file.py", scripts_dir);
|
||||
if !std::path::Path::new(&script).exists() {
|
||||
return minimal_probe(format_base);
|
||||
@@ -184,18 +241,12 @@ fn minimal_probe(format_base: serde_json::Value) -> serde_json::Value {
|
||||
|
||||
/// Unified probe: dispatches to the right probe based on file type
|
||||
/// Returns a probe_json-compatible Value
|
||||
pub async fn unified_probe(
|
||||
path: &Path,
|
||||
scripts_dir: &str,
|
||||
python_path: &str,
|
||||
) -> serde_json::Value {
|
||||
pub async fn unified_probe(path: &Path, scripts_dir: &str, python_path: &str) -> serde_json::Value {
|
||||
let cat = detect_category(path);
|
||||
let format_base = base_format_info(path);
|
||||
|
||||
match cat {
|
||||
FileCategory::Video | FileCategory::Image => {
|
||||
ffprobe_probe(path, format_base)
|
||||
}
|
||||
FileCategory::Video | FileCategory::Image => ffprobe_probe(path, format_base),
|
||||
FileCategory::Document | FileCategory::Spreadsheet | FileCategory::Presentation => {
|
||||
python_probe(path, &cat, scripts_dir, python_path, format_base)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user