Cactus/commands/
command_line.rs

1use colored::Colorize;
2use log::{debug, info, warn};
3use tokio::io::{AsyncBufReadExt, BufReader};
4
5use crate::{config::Settings, consts, fs_manager, gracefully_exit, player};
6
7// Asynchronously handles user input. It never returns
8
9// TODO: IMPLEMENT COMMANDS SEPARATELY FROM THIS FUNCTION, otherwise the code will just be as good as a dumpster fire
10// TODO: use the 'Command Pattern' and command handlers
11pub async fn handle_input() -> ! {
12    let mut reader = BufReader::new(tokio::io::stdin());
13    let mut buffer = String::new();
14
15    loop {
16        buffer.clear();
17        if let Ok(bytes_read) = reader.read_line(&mut buffer).await {
18            if bytes_read == 0 {
19                continue; // EOF
20            }
21        }
22
23        debug!("you entered: {buffer}");
24
25        if buffer.trim().to_lowercase() == "stop" {
26            let content = "Server will stop in few second…";
27            warn!("{}", content.red().bold());
28            gracefully_exit(crate::ExitCode::Failure)
29        }
30
31        if buffer.trim().to_lowercase().starts_with("op") {
32            let mut parts = buffer.split_whitespace();
33            parts.next(); // Ignore the "op" command itself
34
35            if let Some(player_name) = parts.next() {
36                match player::get_uuid(player_name).await {
37                    Ok(uuid) if !uuid.is_empty() => {
38                        // If player exist try to put it into ops.json.
39                        let content = match fs_manager::write_ops_json(
40                            consts::file_paths::OPERATORS,
41                            &uuid,
42                            player_name,
43                            Settings::new().op_permission_level,
44                            true,
45                        ) {
46                            Ok(_) => "".to_string(),
47                            Err(e) => format!(
48                                "Failed to make {} a server operator, error: {}",
49                                player_name, e
50                            ),
51                        };
52                        info!("{}", content);
53                    }
54                    _ => {
55                        // Invalid player
56                        warn!("That player does not exist");
57                    }
58                }
59            } else {
60                warn!("Missing one argument: op <player_name>");
61            }
62        }
63    }
64}