diff --git a/src/error.rs b/src/error.rs index 60b33ac..679f70b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -90,6 +90,9 @@ pub(crate) enum UploadError { #[error("Unsupported image format")] UnsupportedFormat, + #[error("Gif uploads are not enabled")] + SilentVideoDisabled, + #[error("Invalid media dimensions")] Dimensions, @@ -143,7 +146,9 @@ impl ResponseError for Error { UploadError::DuplicateAlias | UploadError::Limit(_) | UploadError::NoFiles - | UploadError::Upload(_), + | UploadError::Upload(_) + | UploadError::UnsupportedFormat + | UploadError::SilentVideoDisabled, ) => StatusCode::BAD_REQUEST, Some( UploadError::Sled(crate::repo::sled::SledError::Missing) diff --git a/src/main.rs b/src/main.rs index 147edc3..87e6957 100644 --- a/src/main.rs +++ b/src/main.rs @@ -212,7 +212,10 @@ async fn download( futures_util::pin_mut!(stream); let permit = PROCESS_SEMAPHORE.acquire().await?; - let session = manager.session((**store).clone()).upload(stream).await?; + let session = manager + .session((**store).clone()) + .upload(CONFIG.media.enable_silent_video, stream) + .await?; let alias = session.alias().unwrap().to_owned(); drop(permit); let delete_token = session.delete_token().await?; @@ -658,7 +661,10 @@ async fn launch( let res = manager .session(store) - .upload(map_error::map_crate_error(stream)) + .upload( + CONFIG.media.enable_silent_video, + map_error::map_crate_error(stream), + ) .await; drop(permit); @@ -694,6 +700,7 @@ async fn launch( .import( filename, validate_imports, + CONFIG.media.enable_silent_video, map_error::map_crate_error(stream), ) .await; diff --git a/src/upload_manager/session.rs b/src/upload_manager/session.rs index 726ac77..390d758 100644 --- a/src/upload_manager/session.rs +++ b/src/upload_manager/session.rs @@ -113,6 +113,7 @@ impl UploadManagerSession { mut self, alias: String, validate: bool, + enable_silent_video: bool, mut stream: impl Stream> + Unpin, ) -> Result { let mut bytes_mut = actix_web::web::BytesMut::new(); @@ -127,6 +128,7 @@ impl UploadManagerSession { let (_, validated_reader) = crate::validate::validate_image_bytes( bytes_mut.freeze(), self.manager.inner.format, + enable_silent_video, validate, ) .await?; @@ -150,6 +152,7 @@ impl UploadManagerSession { #[instrument(skip(self, stream))] pub(crate) async fn upload( mut self, + enable_silent_video: bool, mut stream: impl Stream> + Unpin, ) -> Result { let mut bytes_mut = actix_web::web::BytesMut::new(); @@ -164,6 +167,7 @@ impl UploadManagerSession { let (input_type, validated_reader) = crate::validate::validate_image_bytes( bytes_mut.freeze(), self.manager.inner.format, + enable_silent_video, true, ) .await?; diff --git a/src/validate.rs b/src/validate.rs index d6bfa44..0a78159 100644 --- a/src/validate.rs +++ b/src/validate.rs @@ -1,5 +1,9 @@ use crate::{ - config::ImageFormat, either::Either, error::Error, ffmpeg::InputFormat, magick::ValidInputType, + config::ImageFormat, + either::Either, + error::{Error, UploadError}, + ffmpeg::InputFormat, + magick::ValidInputType, }; use actix_web::web::Bytes; use tokio::io::AsyncRead; @@ -36,6 +40,7 @@ impl AsyncRead for UnvalidatedBytes { pub(crate) async fn validate_image_bytes( bytes: Bytes, prescribed_format: Option, + enable_silent_video: bool, validate: bool, ) -> Result<(ValidInputType, impl AsyncRead + Unpin), Error> { let input_type = crate::magick::input_type_bytes(bytes.clone()).await?; @@ -45,18 +50,28 @@ pub(crate) async fn validate_image_bytes( } match (prescribed_format, input_type) { - (_, ValidInputType::Gif) => Ok(( - ValidInputType::Mp4, - Either::right(Either::left( - crate::ffmpeg::to_mp4_bytes(bytes, InputFormat::Gif).await?, - )), - )), - (_, ValidInputType::Mp4) => Ok(( - ValidInputType::Mp4, - Either::right(Either::left( - crate::ffmpeg::to_mp4_bytes(bytes, InputFormat::Mp4).await?, - )), - )), + (_, ValidInputType::Gif) => { + if !enable_silent_video { + return Err(UploadError::SilentVideoDisabled.into()); + } + Ok(( + ValidInputType::Mp4, + Either::right(Either::left( + crate::ffmpeg::to_mp4_bytes(bytes, InputFormat::Gif).await?, + )), + )) + } + (_, ValidInputType::Mp4) => { + if !enable_silent_video { + return Err(UploadError::SilentVideoDisabled.into()); + } + Ok(( + ValidInputType::Mp4, + Either::right(Either::left( + crate::ffmpeg::to_mp4_bytes(bytes, InputFormat::Mp4).await?, + )), + )) + } (Some(ImageFormat::Jpeg) | None, ValidInputType::Jpeg) => Ok(( ValidInputType::Jpeg, Either::right(Either::right(Either::left(