From 9b5432889223984ab95ba670080eed6f5c843635 Mon Sep 17 00:00:00 2001 From: Falko Zurell Date: Mon, 18 Nov 2024 23:39:10 +0100 Subject: [PATCH] added hint to .env file when calling the program --- README.md | 2 ++ src/main.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 0e93778..56c396d 100644 --- a/README.md +++ b/README.md @@ -25,3 +25,5 @@ Generated description: Aerial view of a circular lake surrounded by dense forest Successfully uploaded image to WordPress with description Image URL: https://example.wordpress.com/wp-content/uploads/2024/11/DJI_0247-scaled.jpg ``` + +Hint: make sure that the `.env` file is located in $PWD when calling the script diff --git a/src/main.rs b/src/main.rs index f4d800d..d45cf4c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ use reqwest::{self, multipart}; use serde_json::{json, Value}; use std::env; use std::error::Error; -use std::path::Path; +use std::path::{Path, PathBuf}; use tokio; use base64::{Engine as _, engine::general_purpose::STANDARD}; @@ -32,6 +32,38 @@ impl Config { } } +fn validate_image_path(path_str: &str) -> Result> { + let path = PathBuf::from(path_str); + + // Check if path exists + if !path.exists() { + return Err(format!("Image path does not exist: {}", path_str).into()); + } + + // Check if it's a file + if !path.is_file() { + return Err(format!("Path is not a file: {}", path_str).into()); + } + + // Check file extension + match path.extension().and_then(|ext| ext.to_str()) { + Some(ext) => { + let lower_ext = ext.to_lowercase(); + if !["jpg", "jpeg", "png", "gif"].contains(&lower_ext.as_str()) { + return Err(format!("Unsupported file type: {}", ext).into()); + } + } + None => return Err("File has no extension".into()), + } + + // Try to canonicalize the path (resolve symlinks and normalize) + let canonical_path = path.canonicalize() + .map_err(|e| format!("Failed to resolve path: {}", e))?; + + println!("Using image file: {}", canonical_path.display()); + Ok(canonical_path) +} + #[tokio::main] async fn main() -> Result<(), Box> { // Get image path from command line arguments @@ -40,24 +72,29 @@ async fn main() -> Result<(), Box> { eprintln!("Usage: {} ", args[0]); std::process::exit(1); } - let image_path = &args[1]; + + // Validate and normalize the image path + let image_path = validate_image_path(&args[1])?; // Load configuration let config = Config::from_env()?; // Get image description from ChatGPT - let description = get_image_description(&config, image_path).await?; + let description = get_image_description(&config, &image_path).await?; println!("Generated description: {}", description); // Upload image to WordPress and set ALT text - upload_to_wordpress(&config, image_path, &description).await?; + upload_to_wordpress(&config, &image_path, &description).await?; Ok(()) } -async fn get_image_description(config: &Config, image_path: &str) -> Result> { +async fn get_image_description(config: &Config, image_path: &Path) -> Result> { // Read and encode image - let image_data = std::fs::read(image_path)?; + let image_data = tokio::fs::read(image_path) + .await + .map_err(|e| format!("Failed to read image file: {}", e))?; + let base64_image = STANDARD.encode(&image_data); // Create ChatGPT API request @@ -67,7 +104,7 @@ async fn get_image_description(config: &Config, image_path: &str) -> Result Result Result<(), Box> { let client = reqwest::Client::new(); - let file_data = tokio::fs::read(image_path).await?; - let filename = Path::new(image_path) + let file_data = tokio::fs::read(image_path) + .await + .map_err(|e| format!("Failed to read image for upload: {}", e))?; + + let filename = image_path .file_name() .ok_or("Invalid filename")? .to_str()