diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/birka-web.rs | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/src/birka-web.rs b/src/birka-web.rs index 2053805..4e518aa 100644 --- a/src/birka-web.rs +++ b/src/birka-web.rs @@ -85,6 +85,26 @@ struct FileResult { tags: Vec<String>, } +/// Return whether or not `filename` ends with one of `extensions`. +fn has_extension<T: AsRef<Path>>(filename: T, extensions: Vec<&str>) -> bool { + filename + .as_ref() + .extension() + .and_then(|ext| ext.to_str()) + .map(|ext| extensions.contains(&ext)) + .unwrap_or(false) +} + +/// Return whether or not `filename` ends with the extension of a known video file type. +fn is_video<T: AsRef<Path>>(filename: T) -> bool { + has_extension(filename, vec!["mp4", "mkv", "webm"]) +} + +/// Return whether or not `filename` ends with the extension of a known image file type. +fn is_image<T: AsRef<Path>>(filename: T) -> bool { + has_extension(filename, vec!["png", "jpg", "jpeg", "gif"]) +} + /// Return the store file name of `filename`. fn store_filename<T: AsRef<Path>>(id: i64, path: T) -> String { if let Some(filename) = path.as_ref().file_name() { @@ -101,10 +121,10 @@ fn store_filename<T: AsRef<Path>>(id: i64, path: T) -> String { /// Return the store file name of the thumbnail of `filename`. fn thumb_filename<T: AsRef<Path>>(id: i64, path: T) -> String { - if let Some(filename) = path.as_ref().file_name() { - let filename = filename.to_string_lossy(); - if let Some(n) = filename.rfind('.') { - format!("{id}_thumb.{ext}", id = id, ext = &filename[n + 1..]) + if let Some(ext) = path.as_ref().extension() { + if let Some(ext) = ext.to_str() { + let ext = if is_video(path.as_ref()) { "png" } else { ext }; + format!("{id}_thumb.{ext}", id = id, ext = ext) } else { format!("{}_thumb", id) } @@ -287,6 +307,9 @@ fn display_post(conn: SiteState, id: i64) -> Result<Template> { tags: Vec<String>, filename: String, orig_filename: String, + is_image: bool, + is_video: bool, + is_unknown: bool, } let tb = &conn @@ -304,6 +327,9 @@ fn display_post(conn: SiteState, id: i64) -> Result<Template> { .ok_or(anyhow!("Could not parse filename"))?, ); + let is_image = is_image(&file.path); + let is_video = is_video(&file.path); + Ok(Template::render( "image", Context { @@ -311,6 +337,9 @@ fn display_post(conn: SiteState, id: i64) -> Result<Template> { orig_filename, tags: file.tags, filename: store_filename(file.id, &file.path), + is_image, + is_video, + is_unknown: !is_image && !is_video, }, )) } @@ -332,6 +361,18 @@ fn add_to_store(file: &database::File, file_dir: &str) { im.thumbnail(100, 100) .write_to(out, ImageFormat::Png) .unwrap(); + } else if is_video(&file.path) { + // FIXME: Can we do this... natively? + std::process::Command::new("ffmpeg") + .arg("-i") + .arg(&store_path) + .arg("-vframes") + .arg("1") + .arg("-s") + .arg("100x100") + .arg(&thumb_path) + .output() + .expect("failed to execute process"); } else { let src = Path::new("./static/img/missing_thumb.png"); symlink(src.canonicalize().unwrap(), &thumb_path).unwrap(); |