use crate::responses::Part;
use anyhow::{anyhow, Result};
use base64::{engine::general_purpose::STANDARD, Engine as _};
use std::fs::File;
use std::io::Read;
use std::io::Write;
use std::thread;
use std::time::Duration;
pub fn extract_text_from_partial_json(partial_json: &str) -> Option<String> {
if let Some(start_index) = partial_json.find("\"text\": \"") {
if let Some(end_index) = partial_json[start_index + "\"text\": \"".len()..].find('\"') {
let text_value = &partial_json[start_index + "\"text\": \"".len()
..start_index + "\"text\": \"".len() + end_index];
return Some(text_value.to_owned());
}
}
None
}
pub fn type_with_cursor_effect(text: &str, delay: u64) {
for char in text.chars() {
print!("{}", char);
std::io::stdout().flush().unwrap();
thread::sleep(Duration::from_millis(delay));
}
}
pub fn load_and_encode_image(file_path: &str) -> Result<String> {
let mut file = File::open(file_path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
let base64_encoded = STANDARD.encode(&buffer);
Ok(base64_encoded)
}
pub fn extract_image_or_text(parts: &[Part]) -> Result<Vec<u8>> {
if let Some(base64_data) = parts.iter().find_map(|part| match part {
Part::Image { inline_data } => Some(inline_data.data.clone()),
_ => None,
}) {
let image_bytes = STANDARD.decode(&base64_data)?;
Ok(image_bytes)
} else if let Some(text) = parts.iter().find_map(|part| match part {
Part::Text { text } => Some(text.clone()),
_ => None,
}) {
Err(anyhow!("Expected image but got only text: {}", text))
} else {
Err(anyhow!("No image or text found in response"))
}
}