Skip to main content

nexus_common/models/file/
blob.rs

1use 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}