1#[cfg(feature = "image")]
2use image::{io::Reader as ImageReader, DynamicImage};
3#[cfg(feature = "image")]
4use std::io::Cursor;
5
6use std::process::Command;
7use std::process::Output;
8use std::str::from_utf8;
9
10pub use crate::flameshot_error::FlameshotError;
11pub use crate::params::FullArgs;
12pub use crate::params::GuiArgs;
13pub use crate::params::ScreenArgs;
14pub mod flameshot_error;
15pub mod params;
16
17pub trait CmdParameters {
19 fn generate_args(&self) -> Vec<String>;
20}
21
22#[derive(Clone, Debug, Eq, PartialEq)]
24pub struct FlameshotOutput {
25 pub output: Output,
26 raw_enabled: bool,
27}
28
29fn has_error(stderr: &str) -> bool {
31 stderr.contains("error")
32}
33
34#[cfg(feature = "image")]
35impl FlameshotOutput {
36 pub fn to_dynamic_image(self) -> Result<DynamicImage, FlameshotError> {
38 if !self.raw_enabled {
39 return Err(FlameshotError::Image(
40 "You forgot to add .raw() to the param builder! which is a requirement for converting to a dynamic_image.".to_string(),
41 ));
42 }
43
44 let buffer = Cursor::new(self.output.stdout);
45 let reader = ImageReader::new(buffer).with_guessed_format();
46
47 let img = match reader {
48 Err(e) => return Err(FlameshotError::Image(e.to_string())),
49 Ok(img) => img,
50 };
51
52 match img.decode() {
53 Err(e) => Err(FlameshotError::Image(e.to_string())),
54 Ok(img) => Ok(img),
55 }
56 }
57}
58
59pub fn execute(params: impl CmdParameters) -> Result<FlameshotOutput, FlameshotError> {
61 let args = params.generate_args();
62 let raw_enabled = args.contains(&String::from("--raw"));
63 let output = Command::new("flameshot")
64 .args(args)
65 .output()
66 .map_err(|e| FlameshotError::Os(e.to_string()))?;
67
68 let stderr = from_utf8(&output.stderr).unwrap_or("").to_string();
69
70 match has_error(&stderr) {
71 true => Err(FlameshotError::Os(stderr)),
72 false => Ok(FlameshotOutput {
73 output,
74 raw_enabled,
75 }),
76 }
77}