From 6a9df7023d1509ba06e0ee537a7ca502f6fcf73f Mon Sep 17 00:00:00 2001
From: Falko Zurell <falko.zurell@here.com>
Date: Sat, 8 Mar 2025 20:09:28 +0100
Subject: [PATCH] fixed body encoding issue for Pixelfed posting

---
 src/image_description.rs | 21 ++++++---
 src/pixelfed.rs          | 96 ++++++++++++++++++++--------------------
 2 files changed, 64 insertions(+), 53 deletions(-)

diff --git a/src/image_description.rs b/src/image_description.rs
index 967110c..c55fb3b 100644
--- a/src/image_description.rs
+++ b/src/image_description.rs
@@ -45,12 +45,15 @@ pub fn get_description_from_file(
     //read image caption from a local file that
     //has the same name than the image with the extension ".caption.txt"
     let caption_extension = file_config.caption_extension;
-    let captionname = format!("{}{}", image_name, caption_extension);
+    let captionname = format!("{}{}", &image_name, caption_extension);
 
     debug!("Looking for {}", &captionname);
     let caption_data = std::fs::read_to_string(captionname);
 
-    println!("Description fetched successfully from FILE");
+    println!(
+        "Description fetched successfully from FILE for {}",
+        &image_name
+    );
 
     Ok(caption_data.unwrap())
 }
@@ -61,7 +64,7 @@ pub fn get_description_from_chatgpt(
     chatgpt_config: self::ChatGPTConfig,
 ) -> Result<String, Box<dyn super::Error>> {
     // Read and encode image
-    let image_data = std::fs::read(image_name)?;
+    let image_data = std::fs::read(&image_name)?;
 
     // Base64 encode the image for ChatGTP API
     let base64_image = STANDARD.encode(image_data);
@@ -112,7 +115,10 @@ pub fn get_description_from_chatgpt(
         .as_str()
         .ok_or("Invalid content format in response")?
         .to_string();
-    println!("Description generated successfully from ChatGPT");
+    println!(
+        "Description generated successfully from ChatGPT for {}",
+        &image_name
+    );
 
     Ok(description)
 }
@@ -123,7 +129,7 @@ pub fn get_description_from_ollama(
     ollama_config: OllamaConfig,
 ) -> Result<String, Box<dyn super::Error>> {
     // Read and encode image
-    let image_data = std::fs::read(image_name)?;
+    let image_data = std::fs::read(&image_name)?;
     // Base64 encode the image for ChatGTP API
     let base64_image = STANDARD.encode(image_data);
 
@@ -179,6 +185,9 @@ pub fn get_description_from_ollama(
     };
 
     info!("Description generated by OLLAMA: {}", &description);
-    println!("Description generated successfully from OLLAMA");
+    println!(
+        "Description generated successfully from OLLAMA for {}",
+        &image_name
+    );
     Ok(description)
 }
diff --git a/src/pixelfed.rs b/src/pixelfed.rs
index 40b2e08..18361bd 100644
--- a/src/pixelfed.rs
+++ b/src/pixelfed.rs
@@ -1,5 +1,8 @@
 use log::{debug, error, info, log_enabled, Level};
 use reqwest::{self};
+use serde::{Deserialize, Serialize};
+use serde_json::json;
+
 use std::error::Error;
 use std::time::Duration;
 
@@ -11,6 +14,19 @@ struct PixelfedConfig {
     pixelfed_batch_size: usize,
 }
 
+// Example response structure - customize to your API's response format
+#[derive(Deserialize, Debug)]
+struct SuccessResponse {
+    success: bool,
+    data: ResponseData,
+}
+
+#[derive(Deserialize, Debug)]
+struct ResponseData {
+    id: String,
+    result: String,
+}
+
 fn format_post_text(template: &str, batch_num: usize, total_batches: usize, title: &str) -> String {
     template
         .replace(
@@ -41,24 +57,23 @@ pub fn bulk_upload_images(
         pixelfed_batch_size: config.pixelfed_batch_size.clone(),
     };
 
+    let client = match reqwest::blocking::ClientBuilder::new()
+        .connect_timeout(Duration::new(30, 0))
+        .timeout(Duration::new(300, 0))
+        .connection_verbose(true)
+        .build()
+    {
+        Ok(client) => client,
+        Err(e) => {
+            error!("Failed to build HTTP client: {}", e);
+            return Err(Box::from(e));
+        }
+    };
     // construct the full URL for the Pixelfed Upload
     let url = format!("{}/api/v1/media", pxl_config.pixelfed_url.clone());
 
     // Iterate over all the images we were given
     for image_path in images {
-        let client = match reqwest::blocking::ClientBuilder::new()
-            .connect_timeout(Duration::new(30, 0))
-            .timeout(Duration::new(300, 0))
-            .connection_verbose(true)
-            .build()
-        {
-            Ok(client) => client,
-            Err(e) => {
-                error!("Failed to build HTTP client: {}", e);
-                return Err(Box::from(e));
-            }
-        };
-
         let description: String;
         debug!("Handling image {}", &image_path.to_string());
         // get image description depending on the caption_mode
@@ -148,49 +163,35 @@ pub fn bulk_upload_images(
         };
 
         // upload the form to Pixelfed
-        let res = client
+        let res = match client
             .post(&url)
             .bearer_auth(&pxl_config.pixelfed_access_token)
             .multipart(form)
-            .send();
-
-        let res_json: serde_json::Value = match res {
-            Ok(response) => {
-                if response.status().is_success() {
-                    let rsp: serde_json::Value = response.json()?;
-                    info!("Image uploaded successfully! {}", &rsp.to_string());
-                    rsp.into()
-                } else {
-                    error!("Failed to upload image. Status: {:?}", &response.status());
-                    let error_message = response
-                        .text()
-                        .unwrap_or_else(|_| "Unknown error".to_string());
-                    error!("Error message: {}", error_message);
-                    return Err(Box::from("Failed to upload image"));
-                }
-            }
+            .send()
+        {
+            Ok(result) => result,
             Err(e) => {
                 error!("Failed to send request: {}", e);
                 return Err(Box::from(e));
             }
         };
 
-        let image_id = res_json["id"].as_str().unwrap().to_string();
-        media_ids.push(image_id);
+        let status = res.status();
+
+        // Check if the response status indicates success
+        if status.is_success() {
+            // Parse the success response
+            let success_response: serde_json::Value = res.json()?;
+            let image_id = success_response["id"].clone();
+            media_ids.push(image_id);
+        } else {
+            let error_text = res.text()?;
+            return Err(Box::from(format!("Failed to upload image: {}", error_text)));
+        }
     }
 
-    let client = match reqwest::blocking::ClientBuilder::new()
-        .connect_timeout(Duration::new(30, 0))
-        .timeout(Duration::new(300, 0))
-        .connection_verbose(true)
-        .build()
-    {
-        Ok(client) => client,
-        Err(e) => {
-            error!("Failed to build HTTP client: {}", e);
-            return Err(Box::from(e));
-        }
-    };
+    println!("Done uploading all images: {}", media_ids.len());
+
     if !media_ids.is_empty() {
         let post_url = format!("{}/api/v1/statuses", pxl_config.pixelfed_url);
         let post_text = format_post_text(
@@ -199,11 +200,12 @@ pub fn bulk_upload_images(
             total_batches,
             title,
         );
+
         let body = serde_json::json!({
-            "status": post_text,
+            "status": post_text.to_string(),
             "media_ids": media_ids,
             "alt_texts": media_descriptions,
-            "visibility": pxl_config.pixelfed_visibility,
+            "visibility": pxl_config.pixelfed_visibility.to_string(),
         });
         info!("Body: \n{}", &body.to_string());
         info!("MediaIDs: {}", &media_ids.len());