Skip to main content

robit_agent/
media.rs

1//! Media handling utilities: download, encode, etc.
2
3use std::path::PathBuf;
4
5use base64::{engine::general_purpose, Engine as _};
6use thiserror::Error;
7
8/// Errors that can occur while handling media.
9#[derive(Debug, Error)]
10pub enum MediaError {
11    #[error("HTTP error: {0}")]
12    Http(#[from] reqwest::Error),
13    #[error("IO error: {0}")]
14    Io(#[from] std::io::Error),
15    #[error("Invalid media content: empty or corrupted")]
16    InvalidContent,
17}
18
19/// Download media from URL and save to the specified directory.
20///
21/// Returns the path to the saved file.
22pub async fn download_media(
23    url: &str,
24    filename: Option<&str>,
25    save_dir: &PathBuf,
26) -> Result<PathBuf, MediaError> {
27    // Create directory if it doesn't exist
28    tokio::fs::create_dir_all(save_dir).await?;
29
30    // Determine filename
31    let save_filename = match filename {
32        Some(s) => s.to_string(),
33        None => uuid::Uuid::new_v4().to_string(),
34    };
35    let save_path = save_dir.join(save_filename);
36
37    // Download
38    let client = reqwest::Client::new();
39    let response = client.get(url).send().await?;
40    let bytes = response.bytes().await?;
41
42    if bytes.is_empty() {
43        return Err(MediaError::InvalidContent);
44    }
45
46    tokio::fs::write(&save_path, &bytes).await?;
47
48    Ok(save_path)
49}
50
51/// Download media from URL and encode as base64 data URL.
52///
53/// Returns a string like "data:image/jpeg;base64,...".
54pub async fn download_and_encode_base64(
55    url: &str,
56    content_type: &str,
57) -> Result<String, MediaError> {
58    let client = reqwest::Client::new();
59    let bytes = client.get(url).send().await?.bytes().await?;
60
61    if bytes.is_empty() {
62        return Err(MediaError::InvalidContent);
63    }
64
65    let base64 = general_purpose::STANDARD.encode(&bytes);
66    Ok(format!("data:{};base64,{}", content_type, base64))
67}