nexus_common/models/file/
blob.rs1use crate::media::{
2 processors::{ImageProcessor, VariantProcessor, VideoProcessor},
3 FileVariant, VariantController,
4};
5use crate::types::DynError;
6use pubky_app_specs::PubkyAppBlob;
7use std::path::PathBuf;
8use tokio::{
9 fs::{self, File},
10 io::AsyncWriteExt,
11};
12use tracing::error;
13
14use super::FileDetails;
15
16pub struct Blob;
17
18impl Blob {
19 pub async fn put_to_static(
20 name: String,
21 files_path: PathBuf,
22 blob: &PubkyAppBlob,
23 ) -> Result<(), DynError> {
24 if !fs::metadata(&files_path)
25 .await
26 .is_ok_and(|metadata| metadata.is_dir())
27 {
28 fs::create_dir_all(&files_path).await?;
29 };
30
31 let file_path = files_path.join(name);
32 let mut static_file = File::create_new(file_path).await?;
33 static_file.write_all(&blob.0).await?;
34
35 Ok(())
36 }
37
38 pub async fn get_by_id(
39 file: &FileDetails,
40 variant: &FileVariant,
41 file_path: PathBuf,
42 ) -> Result<String, DynError> {
43 let file_variant_exists =
44 VariantController::check_variant_exists(file, variant.clone(), file_path.clone()).await;
45
46 if file_variant_exists {
47 Ok(VariantController::get_content_type_for_variant(
48 file, variant,
49 ))
50 } else {
51 match Self::put_variant(file, variant, file_path).await {
52 Ok(content_type) => Ok(content_type),
53 Err(err) => {
54 error!(
55 "Creating variant failed for file: {:?} with error: {}",
56 file, err
57 );
58 Err(err)
59 }
60 }
61 }
62 }
63
64 async fn put_variant(
65 file: &FileDetails,
66 variant: &FileVariant,
67 file_path: PathBuf,
68 ) -> Result<String, DynError> {
69 match &file.content_type {
70 content_type if content_type.starts_with("image/") => {
71 ImageProcessor::create_variant(file, variant, file_path).await
72 }
73 content_type if content_type.starts_with("video/") => {
74 VideoProcessor::create_variant(file, variant, file_path).await
75 }
76 _ => Err(format!("Unsupported content type: {}", file.content_type).into()),
77 }
78 }
79}