1use aurora_core::{AuroraResult, Pipeline, Value};
2use std::process::Command;
3
4fn check_tool(name: &str) -> AuroraResult<()> {
5 let status = Command::new("which")
6 .arg(name)
7 .output()
8 .ok()
9 .map(|o| o.status.success())
10 .unwrap_or(false);
11 if !status {
12 return Err(aurora_core::AuroraError::CommandNotFound(
13 format!("{} is not installed (install with: apt install {})", name, name)
14 ));
15 }
16 Ok(())
17}
18
19pub fn qr_encode(text: &str, output: Option<&str>) -> AuroraResult<Pipeline> {
20 check_tool("qrencode")?;
21
22 let mut cmd = Command::new("qrencode");
23 if let Some(out) = output {
24 cmd.args(["-o", out, text]);
25 } else {
26 cmd.arg(text);
27 }
28
29 let result = cmd.output()
30 .map_err(|e| aurora_core::AuroraError::ModuleError(
31 format!("qrencode failed: {}", e)
32 ))?;
33
34 if !result.status.success() {
35 let stderr = String::from_utf8_lossy(&result.stderr);
36 return Err(aurora_core::AuroraError::ModuleError(
37 format!("qrencode failed: {}", stderr)
38 ));
39 }
40
41 Ok(Pipeline::table(
42 vec!["action".into(), "text".into(), "output".into(), "status".into()],
43 vec![vec![
44 Value::String("encode".into()),
45 Value::String(text.into()),
46 Value::String(output.unwrap_or("stdout").into()),
47 Value::String("ok".into()),
48 ]],
49 ))
50}
51
52pub fn qr_decode(input: &str) -> AuroraResult<Pipeline> {
53 check_tool("zbarimg")?;
54
55 let output = Command::new("zbarimg")
56 .arg(input)
57 .output()
58 .map_err(|e| aurora_core::AuroraError::ModuleError(
59 format!("zbarimg failed: {}", e)
60 ))?;
61
62 let stdout = String::from_utf8_lossy(&output.stdout);
63 let stderr = String::from_utf8_lossy(&output.stderr);
64
65 if !output.status.success() && stdout.is_empty() {
66 return Err(aurora_core::AuroraError::ModuleError(
67 format!("zbarimg failed: {}", stderr)
68 ));
69 }
70
71 Ok(Pipeline::table(
72 vec!["decoded".into()],
73 vec![vec![Value::String(stdout.trim().into())]],
74 ))
75}