1 use chrono::Duration;
2 use clap::ArgMatches;
3 use ffsend_api::config::SEND_DEFAULT_EXPIRE_TIME;
4 use prettytable::{format::FormatBuilder, Cell, Row, Table};
5 
6 use crate::client::to_duration;
7 use crate::cmd::matcher::{debug::DebugMatcher, main::MainMatcher, Matcher};
8 use crate::error::ActionError;
9 #[cfg(feature = "clipboard-bin")]
10 use crate::util::ClipboardType;
11 use crate::util::{api_version_list, features_list, format_bool, format_duration};
12 
13 /// A file debug action.
14 pub struct Debug<'a> {
15     cmd_matches: &'a ArgMatches<'a>,
16 }
17 
18 impl<'a> Debug<'a> {
19     /// Construct a new debug action.
new(cmd_matches: &'a ArgMatches<'a>) -> Self20     pub fn new(cmd_matches: &'a ArgMatches<'a>) -> Self {
21         Self { cmd_matches }
22     }
23 
24     /// Invoke the debug action.
25     // TODO: create a trait for this method
invoke(&self) -> Result<(), ActionError>26     pub fn invoke(&self) -> Result<(), ActionError> {
27         // Create the command matchers
28         let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();
29         let matcher_debug = DebugMatcher::with(self.cmd_matches).unwrap();
30 
31         // Create a table for all debug information
32         let mut table = Table::new();
33         table.set_format(FormatBuilder::new().padding(0, 2).build());
34 
35         // The crate version
36         table.add_row(Row::new(vec![
37             Cell::new("Version:"),
38             Cell::new(crate_version!()),
39         ]));
40 
41         // The default host
42         table.add_row(Row::new(vec![
43             Cell::new("Host:"),
44             Cell::new(matcher_debug.host().as_str()),
45         ]));
46 
47         // The history file
48         #[cfg(feature = "history")]
49         table.add_row(Row::new(vec![
50             Cell::new("History file:"),
51             Cell::new(matcher_main.history().to_str().unwrap_or("?")),
52         ]));
53 
54         // The timeouts
55         table.add_row(Row::new(vec![
56             Cell::new("Timeout:"),
57             Cell::new(
58                 &to_duration(matcher_main.timeout())
59                     .map(|t| {
60                         format_duration(
61                             Duration::from_std(t).expect("failed to convert timeout duration"),
62                         )
63                     })
64                     .unwrap_or("disabled".into()),
65             ),
66         ]));
67         table.add_row(Row::new(vec![
68             Cell::new("Transfer timeout:"),
69             Cell::new(
70                 &to_duration(matcher_main.transfer_timeout())
71                     .map(|t| {
72                         format_duration(
73                             Duration::from_std(t)
74                                 .expect("failed to convert transfer timeout duration"),
75                         )
76                     })
77                     .unwrap_or("disabled".into()),
78             ),
79         ]));
80 
81         // The default host
82         table.add_row(Row::new(vec![
83             Cell::new("Default expiry:"),
84             Cell::new(&format_duration(Duration::seconds(
85                 SEND_DEFAULT_EXPIRE_TIME as i64,
86             ))),
87         ]));
88 
89         // Render a list of compiled features
90         table.add_row(Row::new(vec![
91             Cell::new("Features:"),
92             Cell::new(&features_list().join(", ")),
93         ]));
94 
95         // Render a list of compiled features
96         table.add_row(Row::new(vec![
97             Cell::new("API support:"),
98             Cell::new(&api_version_list().join(", ")),
99         ]));
100 
101         // Show used crypto backend
102         table.add_row(Row::new(vec![
103             Cell::new("Crypto backend:"),
104             #[cfg(feature = "crypto-ring")]
105             Cell::new("ring"),
106             #[cfg(feature = "crypto-openssl")]
107             Cell::new("OpenSSL"),
108         ]));
109 
110         // Clipboard information
111         #[cfg(feature = "clipboard-bin")]
112         table.add_row(Row::new(vec![
113             Cell::new("Clipboard:"),
114             Cell::new(&format!("{}", ClipboardType::select())),
115         ]));
116 
117         // Show whether quiet is used
118         table.add_row(Row::new(vec![
119             Cell::new("Quiet:"),
120             Cell::new(format_bool(matcher_main.quiet())),
121         ]));
122 
123         // Show whether verbose is used
124         table.add_row(Row::new(vec![
125             Cell::new("Verbose:"),
126             Cell::new(format_bool(matcher_main.verbose())),
127         ]));
128 
129         // Print the debug table
130         table.printstd();
131 
132         Ok(())
133     }
134 }
135