use serde::Serialize; use std::fs::DirEntry; use std::path::Path; use std::io; use rocket::serde::json::Json; use crate::common::{get_clips_dir, thumbs_dir}; #[derive(Serialize)] pub struct Category { name: String, // NOTE: this is simply a URI pathname // EXAMPLE: /thumbnail//.thumbnail.png thumbnail: String } #[derive(Serialize)] struct List { categories: Vec } pub fn get_category_dirs(path: &str) -> std::io::Result> { let path = std::path::Path::new(path); if !path.is_dir() { let e = io::Error::new(io::ErrorKind::NotFound, "Unable to open"); return Err(e); } let mut ret: Vec = Vec::new(); for entry in std::fs::read_dir(path)? { if let Ok(entry) = entry { if entry.path().is_dir() { ret.push(entry) } } } return Ok(ret); } pub fn get_category_thumbnail(category: &str) -> std::io::Result { let pathname = format!("{}/{}", thumbs_dir(), &category); let path = Path::new(&pathname); // Assume its a directory let item = path.read_dir()?.find(|file| { if let Ok(file) = file { let name = file.file_name().into_string().unwrap(); name == "category-thumbnail.jpg" } else { false } }); return Ok(match item { Some(name) => { let name = name.unwrap().file_name().into_string().unwrap(); format!("/thumbnail/{}/{}", category, name) }, None => "/static/cantfindshit.jpg".to_string() }) } #[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 = get_clips_dir(); let mut cats: Vec = Vec::new(); if let Ok(dirs) = get_category_dirs(&dir) { // Let's just assume that each item in this directory is a folder // That way we can do this blindly without 9999 allocs for d in dirs { let name = d.file_name().to_string_lossy().to_string(); let thumbnail = match get_category_thumbnail(&name) { Ok(s) => s, _ => "/static/cantfindshit.jpg".to_string() }; cats.push(Category {name, thumbnail}); } } Json(cats) }