use base64; use serde::Serialize; use std::fs::DirEntry; use std::{io, env}; use rocket::serde::json::Json; #[derive(Serialize)] pub struct Category { name: String, thumbnail: Option } #[derive(Serialize)] struct List { categories: Vec } fn get_category_metadata(entry: DirEntry) -> io::Result<(String, Option)> { use std::io::Read; let name = entry.file_name().to_string_lossy().to_string(); let mut p = entry.path(); p.push(".thumbnail.jpg"); if p.is_file() { let mut buf = Vec::new(); let mut file = std::fs::File::open(p)?; file.read_to_end(&mut buf)?; let nail = base64::encode(buf).to_string(); return match nail.len() { 0 => Ok((name, None)), _ => Ok((name, Some(nail))) }; } return Ok((String::new(), None)); } fn get_category_dirs(path: &str) -> std::io::Result> { let path = std::path::Path::new(path); if !path.is_dir() { panic!("<{:?}> is not a valid directory", path); } let mut ret: Vec = Vec::new(); for entry in std::fs::read_dir(path)? { if let Ok(entry) = entry { ret.push(entry) } } return Ok(ret); } #[get("/categories")] pub fn list() -> Json> { // WARN: misconfigured servers are just going to get shafted and serve up // a tonne of 500's let dir = match env::var("CLIPS_DIR") { Ok(val) => val, Err(_) => "/media/clips/".to_string() }; match get_category_dirs(&dir) { Ok(entries) => { let mut cats: Vec = Vec::new(); for ent in entries { match get_category_metadata(ent) { Ok((name, thumbnail)) => { cats.push(Category {name, thumbnail}); }, _ => continue } } return Json(cats); }, Err(e) => { eprintln!("ERROR: {}", e); } } Json(Vec::new()) }