1pub mod config;
2pub mod encryption;
3pub mod errors;
4pub mod openai;
5
6use crate::config::{CliArgs, Config};
7use rand::Rng;
8use spinoff::{spinners, Color, Spinner};
9use std::{io, process};
10
11const LOADING_MESSAGES: [&'static str; 7] = [
12 "Asking ChatGPT...",
13 "ChatGPT is thinking...",
14 "ChatGPT is writing...",
15 "Assistant is thinking...",
16 "Assistant is writing...",
17 "Invoking the AI gods...",
18 "Calling an AI friend...",
19];
20
21pub fn run(cli_args: &CliArgs, config: &Config) -> anyhow::Result<String> {
22 if !cli_args.raw {
23 let spinner = Spinner::new(spinners::Dots, get_loading_message(), Color::Blue);
24 let response = openai::ask_chatgpt(
25 cli_args.input.as_str(),
26 cli_args.pre_prompt,
27 config.openai_api_key.as_str(),
28 );
29 spinner.stop();
30 let response = response?;
31 println!("\n{response}");
32
33 if cli_args.pre_prompt == openai::PrePrompt::ShellScript {
34 ask_then_run_script(response.as_str());
35 }
36 Ok(response)
37 } else {
38 let response = openai::ask_chatgpt(
39 cli_args.input.as_str(),
40 cli_args.pre_prompt,
41 config.openai_api_key.as_str(),
42 );
43 let mut response = response?;
44 if cli_args.pre_prompt == openai::PrePrompt::ShellScript {
45 response = openai::extract_code_block_if_needed(response.as_str())
46 }
47 println!("\n{response}");
48 Ok(response)
49 }
50}
51
52fn get_loading_message() -> String {
53 let i = rand::thread_rng().gen_range(0..LOADING_MESSAGES.len());
54 LOADING_MESSAGES[i].to_string()
55}
56
57fn ask_then_run_script(response: &str) {
58 println!("\nDo you want to run this script? (y/N)");
59
60 let mut yes_no = String::new();
61 io::stdin()
62 .read_line(&mut yes_no)
63 .expect("Failed to read your input");
64 yes_no = yes_no.trim().to_lowercase();
65 if yes_no == "y" || yes_no == "yes" || yes_no == "o" || yes_no == "oui" {
66 let script = openai::extract_code_block_if_needed(response);
67 println!("\nExecuting script...\n\n--------------\n\n");
69 let output = process::Command::new("bash")
70 .arg("-c")
71 .arg(script)
72 .output()
73 .expect("Failed to execute script");
74 if !output.stderr.is_empty() {
75 eprintln!(
76 "{}",
77 String::from_utf8(output.stderr)
78 .expect("Could not parse script stderr output as UTF-8")
79 );
80 } else {
81 println!(
82 "{}",
83 String::from_utf8(output.stdout)
84 .expect("Could not parse script stdout output as UTF-8")
85 );
86 }
87 if !output.status.success() {
88 process::exit(1);
89 }
90 }
91}