mail4agent_messenger_shell/cli/
session_arg.rs1use std::path::PathBuf;
6
7use crate::machine::{load_session_records, routine_name_for, HostSession, SESSIONS_DIR_ENV};
8use crate::{session_store_dir, STORE_ROOT_ENV};
9
10#[cfg(test)]
12pub(crate) static ENV_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
13
14pub struct Target {
15 pub session_id: String,
16 pub nick: Option<String>,
17 pub store_root: PathBuf,
18 pub record: Option<HostSession>,
20}
21
22impl Target {
23 pub fn store_dir(&self) -> PathBuf {
24 session_store_dir(&self.store_root, &self.session_id)
25 }
26}
27
28pub fn take_flag(args: &mut Vec<String>, flag: &str) -> Result<Option<String>, String> {
30 let Some(i) = args.iter().position(|a| a == flag) else { return Ok(None) };
31 if i + 1 >= args.len() {
32 return Err(format!("{flag} needs a value"));
33 }
34 let v = args.remove(i + 1);
35 args.remove(i);
36 Ok(Some(v))
37}
38
39pub fn take_switch(args: &mut Vec<String>, flag: &str) -> bool {
40 match args.iter().position(|a| a == flag) {
41 Some(i) => {
42 args.remove(i);
43 true
44 }
45 None => false,
46 }
47}
48
49pub fn resolve(args: &mut Vec<String>) -> Result<Target, String> {
51 let session = take_flag(args, "--session")?;
52 let nick = take_flag(args, "--as")?;
53 let store_root = std::env::var(STORE_ROOT_ENV).ok().filter(|v| !v.is_empty()).map(PathBuf::from).ok_or_else(|| format!("{STORE_ROOT_ENV} is not set"))?;
54 let records = std::env::var(SESSIONS_DIR_ENV).ok().filter(|v| !v.is_empty()).and_then(|d| load_session_records(std::path::Path::new(&d)).ok()).unwrap_or_default();
55 match (session, nick) {
56 (Some(_), Some(_)) => Err("give --session or --as, not both".into()),
57 (None, None) => Err("name the session: --as <nick> or --session <id>".into()),
58 (Some(id), None) => {
59 let record = records.into_iter().find(|r| r.session_id == id);
60 let nick = record.as_ref().and_then(routine_name_for);
61 Ok(Target { session_id: id, nick, store_root, record })
62 }
63 (None, Some(n)) => {
64 let want = crate::nick::lookup_nick(&n).map_err(|e| e.to_string())?;
65 let record = records.into_iter().find(|r| routine_name_for(r).is_some_and(|x| x.eq_ignore_ascii_case(&want))).ok_or_else(|| format!("no session record for {want} in {SESSIONS_DIR_ENV}"))?;
66 Ok(Target { session_id: record.session_id.clone(), nick: Some(want), store_root, record: Some(record) })
67 }
68 }
69}