use crate::constants::env::system;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InboundAttachment {
pub file_uuid: String,
pub file_name: String,
}
pub fn extract_inbound_attachments(msg: &serde_json::Value) -> Vec<InboundAttachment> {
let file_attachments = match msg.get("file_attachments") {
Some(v) => v,
None => return Vec::new(),
};
if let Some(arr) = file_attachments.as_array() {
arr.iter()
.filter_map(|item| {
let file_uuid = item.get("file_uuid")?.as_str()?.to_string();
let file_name = item.get("file_name")?.as_str()?.to_string();
Some(InboundAttachment {
file_uuid,
file_name,
})
})
.collect()
} else {
Vec::new()
}
}
fn sanitize_file_name(name: &str) -> String {
let base = std::path::Path::new(name)
.file_name()
.and_then(|n| n.to_str())
.unwrap_or(name);
let sanitized: String = base
.chars()
.map(|c| {
if c.is_ascii_alphanumeric() || c == '.' || c == '_' || c == '-' {
c
} else {
'_'
}
})
.collect();
if sanitized.is_empty() {
"attachment".to_string()
} else {
sanitized
}
}
fn uploads_dir() -> PathBuf {
let home = std::env::var(system::HOME).unwrap_or_else(|_| "/tmp".to_string());
PathBuf::from(home)
.join(".claude")
.join("uploads")
.join("default")
}
const DOWNLOAD_TIMEOUT_MS: u64 = 30_000;
fn debug(msg: &str) {
eprintln!("[bridge:inbound-attach] {}", msg);
}
pub async fn resolve_inbound_attachments(_attachments: Vec<InboundAttachment>) -> String {
if _attachments.is_empty() {
return String::new();
}
debug(&format!("resolving {} attachment(s)", _attachments.len()));
String::new()
}
pub fn prepend_path_refs(content: &str, prefix: &str) -> String {
if prefix.is_empty() {
return content.to_string();
}
format!("{}{}", prefix, content)
}
pub async fn resolve_and_prepend(msg: &serde_json::Value, content: &str) -> String {
let attachments = extract_inbound_attachments(msg);
if attachments.is_empty() {
return content.to_string();
}
let prefix = resolve_inbound_attachments(attachments).await;
prepend_path_refs(content, &prefix)
}