use anyhow::{Result, bail};
use imessage_core::macos::MacOsVersion;
use tracing::warn;
use crate::process::{execute_applescript, safe_execute_applescript};
use crate::scripts;
pub async fn send_message(
chat_guid: &str,
message: &str,
attachment: &str,
_is_audio_message: bool,
v: MacOsVersion,
format_address: &(dyn Fn(&str) -> String + Send + Sync),
) -> Result<()> {
let script = scripts::send_message(chat_guid, message, attachment, v, format_address);
let Some(script) = script else {
bail!("Cannot send message: missing chat GUID or content");
};
match execute_applescript(&script).await {
Ok(_) => Ok(()),
Err(e) => {
let err_msg = e.to_string();
if err_msg.contains("timed out") {
bail!("{err_msg}");
}
warn!("Primary send failed: {e}, restarting Messages and retrying...");
let restart = scripts::restart_messages(3);
let _ = safe_execute_applescript(&restart).await;
match execute_applescript(&script).await {
Ok(_) => Ok(()),
Err(retry_err) => {
warn!("Primary send retry failed: {retry_err}");
let address = scripts::get_address_from_input(chat_guid);
if !address.starts_with("chat") {
let fallback =
scripts::send_message_fallback(chat_guid, message, attachment);
match fallback {
Ok(Some(fb_script)) => {
execute_applescript(&fb_script).await?;
return Ok(());
}
Ok(None) => bail!("Fallback script returned None"),
Err(fb_err) => bail!("All send attempts failed: {fb_err}"),
}
}
bail!("All send attempts failed: {retry_err}");
}
}
}
}
}
pub async fn start_messages() -> Result<()> {
let script = scripts::start_messages();
let _ = safe_execute_applescript(&script).await;
Ok(())
}
pub async fn create_chat(
participants: &[String],
service: &str,
message: Option<&str>,
) -> Result<String> {
let start = scripts::start_messages();
let _ = safe_execute_applescript(&start).await;
let script = scripts::start_chat(participants, service, message);
let output = execute_applescript(&script).await?;
Ok(output)
}
#[cfg(test)]
mod tests {
}