use bingle_core::api::bingle_api::StartOptions;
use bingle_core::util::cli_utils::parse_start_options_from_args;
const HANDLE_FROM_STATE_FILE: &str = "__bingle_chat_handle_from_state_file__";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StoreForwardMode {
Both,
Send,
Receive,
None,
}
impl StoreForwardMode {
fn parse(value: &str) -> Result<StoreForwardMode, String> {
match value {
"both" => Ok(StoreForwardMode::Both),
"send" => Ok(StoreForwardMode::Send),
"receive" => Ok(StoreForwardMode::Receive),
"none" => Ok(StoreForwardMode::None),
other => Err(format!(
"--store-forward expects one of both|send|receive|none, got '{other}'"
)),
}
}
pub fn gates(self) -> (bool, bool) {
match self {
StoreForwardMode::Both => (true, true),
StoreForwardMode::Send => (true, false),
StoreForwardMode::Receive => (false, true),
StoreForwardMode::None => (false, false),
}
}
}
#[derive(Debug)]
pub struct ChatArgs {
pub opts: StartOptions,
pub to: Option<String>,
pub to_id: Option<String>,
pub state_file: Option<String>,
pub no_retries: bool,
pub store_forward: StoreForwardMode,
pub notify_url: Option<String>,
pub poll_interval_secs: Option<u64>,
pub auto_migrate: bool,
}
pub fn parse_chat_args(args: Vec<String>) -> Result<ChatArgs, String> {
let mut to: Option<String> = None;
let mut to_id: Option<String> = None;
let mut state_file: Option<String> = None;
let mut no_retries = false;
let mut store_forward = StoreForwardMode::None;
let mut notify_url: Option<String> = None;
let mut poll_interval_secs: Option<u64> = None;
let mut auto_migrate = false;
let mut rest: Vec<String> = Vec::with_capacity(args.len());
let mut it = args.into_iter();
while let Some(arg) = it.next() {
match arg.as_str() {
"--to" => {
to = Some(it.next().ok_or("--to requires a <handle> value")?);
}
"--to-id" => {
to_id = Some(it.next().ok_or("--to-id requires an <id> value")?);
}
"--state_file" | "--state-file" => {
state_file = Some(it.next().ok_or("--state_file requires a <file> value")?);
}
"--no-retries" | "--no-retry" => {
no_retries = true;
}
"--store-forward" => {
let value = it
.next()
.ok_or("--store-forward requires a <both|send|receive|none> value")?;
store_forward = StoreForwardMode::parse(&value)?;
}
"--notify" => {
notify_url = Some(it.next().ok_or("--notify requires a <url> value")?);
}
"--poll-interval" => {
let value = it.next().ok_or("--poll-interval requires a <secs> value")?;
let secs = value.parse::<u64>().map_err(|_| {
format!("--poll-interval expects a whole number of seconds, got '{value}'")
})?;
poll_interval_secs = Some(secs);
}
"--auto-migrate" => {
auto_migrate = true;
}
"--debug" | "--info" | "--warn" => {}
_ => rest.push(arg),
}
}
if to.is_some() && to_id.is_some() {
return Err("--to and --to-id are mutually exclusive".to_string());
}
let opts = match parse_start_options_from_args(rest.clone()) {
Ok(o) => o,
Err(e) if state_file.is_some() && e.starts_with("Missing handle") => {
let mut with_placeholder = rest;
with_placeholder.push(HANDLE_FROM_STATE_FILE.to_string());
let mut o = parse_start_options_from_args(with_placeholder)?;
o.handle = String::new();
o
}
Err(e) => return Err(e),
};
Ok(ChatArgs {
opts,
to,
to_id,
state_file,
no_retries,
store_forward,
notify_url,
poll_interval_secs,
auto_migrate,
})
}