clippable/api/src/video.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

72 lines
2.2 KiB
Rust

use std::path::{Path, PathBuf};
use std::fs::DirEntry;
use std::ffi::OsStr;
use serde::Serialize;
use rocket::serde::json::Json;
use rocket::fs::NamedFile;
use crate::common::get_clips_dir;
#[derive(Serialize)]
pub struct VideoPreview {
/// Real filename on disk
name: String,
/// URI path to what the browser can reasonably expect
thumbnail: Option<String>
}
fn vid_file_entries(path: &OsStr) -> std::io::Result<Vec<DirEntry>> {
let mut dir = get_clips_dir();
dir.push('/'); dir.push_str(&path.to_string_lossy());
let path = std::path::Path::new(&dir);
if !path.is_dir() {
panic!("<{:?}> is not a valid directory", path);
}
let mut entries: Vec<DirEntry> = Vec::new();
for ent in (path.read_dir()?).flatten() {
let name = ent.file_name().into_string().unwrap();
if name.ends_with("mkv") || name.ends_with("mp4") || name.ends_with("webm") {
entries.push(ent);
}
}
Ok(entries)
}
#[get("/category/<cat..>")]
pub fn list(cat: PathBuf) -> Option<Json<Vec<VideoPreview>>> {
/*
* List out the videos to a given category
*/
// First we have to make sure this given category is even registered with us
let file_path = cat.file_name().unwrap_or_else(|| OsStr::new(""));
if let Ok(entries) = vid_file_entries(file_path) {
let mut previews: Vec<VideoPreview> = Vec::new();
// Autismo but at least its bare-able
for ent in entries {
let name = ent.file_name();
let name = name.to_string_lossy();
let cat = cat.to_string_lossy();
let thumbnail = format!("/thumbnail/{}/{}.jpg", cat, name);
let item = VideoPreview {
name: name.to_string(),
thumbnail: Some(thumbnail)
};
previews.push(item);
}
return Some(Json(previews))
}
None
}
/// Endpoint returns the video file itself that is saved on the server
#[get("/<cat>/<file>")]
pub async fn get_video(cat: PathBuf, file: PathBuf) -> Option<NamedFile> {
let clips_dir = get_clips_dir();
let path = Path::new(&clips_dir).join(cat).join(file);
NamedFile::open(path).await.ok()
}