clippable/api/src/category.rs
shockrah 86b9081354 + Rust docs where needed
There may be more changes that could be
added to improve documentation however
this is meant to be a good start.

!+ There is also a new redirect endpoint for /admin/dashboard
This just a convenience thing so that people
don't have to remember the '/dashboard'
part of the admin route.
2022-03-26 21:51:07 -07:00

81 lines
2.5 KiB
Rust

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};
/// Describes a category of videos as
#[derive(Serialize)]
pub struct Category {
name: String,
/// NOTE: this is simply a URI pathname
/// EXAMPLE: /thumbnail/<category>/.thumbnail.png
thumbnail: String
}
/// Returns a vector of category directories
pub fn get_category_dirs(path: &str) -> std::io::Result<Vec<DirEntry>> {
let path = std::path::Path::new(path);
// Trying to ignore non-directory entries
if !path.is_dir() {
let e = io::Error::new(io::ErrorKind::NotFound, "Unable to open");
return Err(e);
}
let mut ret: Vec<DirEntry> = Vec::new();
for entry in (std::fs::read_dir(path)?).flatten() {
if entry.path().is_dir() {
ret.push(entry)
}
}
Ok(ret)
}
/// Will return the path to a category's thumb nail assuming it exists.
/// If nothing is found then it gives back the URI path to a not-found image
pub fn get_category_thumbnail(category: &str) -> std::io::Result<String> {
let pathname = format!("{}/{}", thumbs_dir(), &category);
let path = Path::new(&pathname);
// Assume directory as we're only called from "safe" places
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()
})
}
/// WARN: misconfigured servers are just going to get shafted and serve up
/// a tonne of 500's
#[get("/categories")]
pub fn list() -> Json<Vec<Category>> {
let dir = get_clips_dir();
let mut cats: Vec<Category> = 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)
}