bhcli

A TUI for chatting on LE PHP Chats
git clone https://git.dasho.dev/bhcli.git
Log | Files | Refs | README

misc.rs (8822B)


      1 use crate::chatops::{ChatCommand, ChatOpError, ChatOpResult, CommandContext};
      2 use std::process::Command;
      3 
      4 /// ASCII art generation
      5 pub struct AsciiCommand;
      6 
      7 impl ChatCommand for AsciiCommand {
      8    fn name(&self) -> &'static str {
      9        "ascii"
     10    }
     11    fn description(&self) -> &'static str {
     12        "Generate ASCII art text"
     13    }
     14    fn usage(&self) -> &'static str {
     15        "/ascii <text>"
     16    }
     17 
     18    fn execute(
     19        &self,
     20        args: Vec<String>,
     21        _context: &CommandContext,
     22    ) -> Result<ChatOpResult, ChatOpError> {
     23        if args.is_empty() {
     24            return Err(ChatOpError::MissingArguments(
     25                "Please specify text to convert".to_string(),
     26            ));
     27        }
     28 
     29        let text = args.join(" ");
     30 
     31        // Try using figlet if available
     32        match Command::new("figlet").arg(&text).output() {
     33            Ok(output) => {
     34                if output.status.success() {
     35                    let result = String::from_utf8_lossy(&output.stdout);
     36                    Ok(ChatOpResult::CodeBlock(
     37                        result.to_string(),
     38                        Some("text".to_string()),
     39                    ))
     40                } else {
     41                    Ok(self.simple_ascii_art(&text))
     42                }
     43            }
     44            Err(_) => {
     45                // Fallback to simple ASCII art
     46                Ok(self.simple_ascii_art(&text))
     47            }
     48        }
     49    }
     50 }
     51 
     52 impl AsciiCommand {
     53    fn simple_ascii_art(&self, text: &str) -> ChatOpResult {
     54        // Simple block letters fallback
     55        let mut result = String::new();
     56 
     57        for ch in text.to_uppercase().chars() {
     58            match ch {
     59                'A' => result.push_str(" █████ \n██   ██\n███████\n██   ██\n██   ██\n"),
     60                'B' => result.push_str("██████ \n██   ██\n██████ \n██   ██\n██████ \n"),
     61                'C' => result.push_str(" ██████\n██     \n██     \n██     \n ██████\n"),
     62                'D' => result.push_str("██████ \n██   ██\n██   ██\n██   ██\n██████ \n"),
     63                'E' => result.push_str("███████\n██     \n█████  \n██     \n███████\n"),
     64                ' ' => result.push_str("       \n       \n       \n       \n       \n"),
     65                _ => result.push_str("██   ██\n██   ██\n██   ██\n██   ██\n██   ██\n"),
     66            }
     67        }
     68 
     69        ChatOpResult::CodeBlock(result, Some("text".to_string()))
     70    }
     71 }
     72 
     73 /// Fortune command
     74 pub struct FortuneCommand;
     75 
     76 impl ChatCommand for FortuneCommand {
     77    fn name(&self) -> &'static str {
     78        "fortune"
     79    }
     80    fn description(&self) -> &'static str {
     81        "Get a random fortune cookie"
     82    }
     83    fn usage(&self) -> &'static str {
     84        "/fortune"
     85    }
     86 
     87    fn execute(
     88        &self,
     89        _args: Vec<String>,
     90        _context: &CommandContext,
     91    ) -> Result<ChatOpResult, ChatOpError> {
     92        match Command::new("fortune").output() {
     93            Ok(output) => {
     94                if output.status.success() {
     95                    let result = String::from_utf8_lossy(&output.stdout);
     96                    Ok(ChatOpResult::Message(format!("🥠 {}", result.trim())))
     97                } else {
     98                    Ok(self.fallback_fortune())
     99                }
    100            }
    101            Err(_) => Ok(self.fallback_fortune()),
    102        }
    103    }
    104 }
    105 
    106 impl FortuneCommand {
    107    fn fallback_fortune(&self) -> ChatOpResult {
    108        let fortunes = vec![
    109            "The best way to predict the future is to invent it.",
    110            "Programs must be written for people to read, and only incidentally for machines to execute.",
    111            "Any fool can write code that a computer can understand. Good programmers write code that humans can understand.",
    112            "First, solve the problem. Then, write the code.",
    113            "Experience is the name everyone gives to their mistakes.",
    114            "In order to be irreplaceable, one must always be different.",
    115            "Java is to JavaScript what car is to Carpet.",
    116            "There are only two hard things in Computer Science: cache invalidation and naming things.",
    117            "Code is like humor. When you have to explain it, it's bad.",
    118            "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning.",
    119        ];
    120 
    121        use rand::seq::SliceRandom;
    122        let mut rng = rand::thread_rng();
    123        let fortune = fortunes.choose(&mut rng).unwrap_or(&fortunes[0]);
    124 
    125        ChatOpResult::Message(format!("🥠 {}", fortune))
    126    }
    127 }
    128 
    129 /// Message of the day
    130 pub struct MotdCommand;
    131 
    132 impl ChatCommand for MotdCommand {
    133    fn name(&self) -> &'static str {
    134        "motd"
    135    }
    136    fn description(&self) -> &'static str {
    137        "Show message of the day"
    138    }
    139    fn usage(&self) -> &'static str {
    140        "/motd"
    141    }
    142 
    143    fn execute(
    144        &self,
    145        _args: Vec<String>,
    146        _context: &CommandContext,
    147    ) -> Result<ChatOpResult, ChatOpError> {
    148        let motd = vec![
    149            "📢 **Message of the Day**".to_string(),
    150            "".to_string(),
    151            "🚀 Welcome to BHCLI with ChatOps!".to_string(),
    152            "💡 Type `/help` to see all available developer commands".to_string(),
    153            "🔧 Use `/commands` to list commands available to your role".to_string(),
    154            "🤖 Try `/explain <concept>` to learn about programming topics".to_string(),
    155            "📦 Check packages with `/crates`, `/npm`, or `/pip`".to_string(),
    156            "🌐 Test networks with `/ping`, `/dig`, or `/whois`".to_string(),
    157            "".to_string(),
    158            "Happy hacking! 🎯".to_string(),
    159        ];
    160 
    161        Ok(ChatOpResult::Block(motd))
    162    }
    163 }
    164 
    165 /// AFK (Away From Keyboard) status
    166 pub struct AfkCommand;
    167 
    168 impl ChatCommand for AfkCommand {
    169    fn name(&self) -> &'static str {
    170        "afk"
    171    }
    172    fn description(&self) -> &'static str {
    173        "Set yourself as away from keyboard"
    174    }
    175    fn usage(&self) -> &'static str {
    176        "/afk [message]"
    177    }
    178 
    179    fn execute(
    180        &self,
    181        args: Vec<String>,
    182        context: &CommandContext,
    183    ) -> Result<ChatOpResult, ChatOpError> {
    184        let message = if args.is_empty() {
    185            "Away from keyboard".to_string()
    186        } else {
    187            args.join(" ")
    188        };
    189 
    190        // In a real implementation, you'd store this in user state
    191        Ok(ChatOpResult::Message(format!(
    192            "💤 {} is now AFK: {}",
    193            context.username, message
    194        )))
    195    }
    196 }
    197 
    198 /// User alias management
    199 pub struct AliasCommand;
    200 
    201 impl ChatCommand for AliasCommand {
    202    fn name(&self) -> &'static str {
    203        "alias"
    204    }
    205    fn description(&self) -> &'static str {
    206        "Create personal command aliases"
    207    }
    208    fn usage(&self) -> &'static str {
    209        "/alias <name> <command> OR /alias list OR /alias remove <name>"
    210    }
    211 
    212    fn execute(
    213        &self,
    214        args: Vec<String>,
    215        _context: &CommandContext,
    216    ) -> Result<ChatOpResult, ChatOpError> {
    217        if args.is_empty() {
    218            return Err(ChatOpError::MissingArguments(
    219                "Please specify alias operation".to_string(),
    220            ));
    221        }
    222 
    223        match args[0].as_str() {
    224            "list" => {
    225                // In a real implementation, you'd load user's aliases from storage
    226                Ok(ChatOpResult::Message(format!(
    227                    "📝 Your aliases: (feature requires persistent storage implementation)"
    228                )))
    229            }
    230            "remove" | "rm" => {
    231                if args.len() < 2 {
    232                    return Err(ChatOpError::MissingArguments(
    233                        "Please specify alias name to remove".to_string(),
    234                    ));
    235                }
    236                let alias_name = &args[1];
    237                Ok(ChatOpResult::Message(format!(
    238                    "🗑️ Removed alias '{}' (feature requires persistent storage implementation)",
    239                    alias_name
    240                )))
    241            }
    242            _ => {
    243                if args.len() < 2 {
    244                    return Err(ChatOpError::MissingArguments(
    245                        "Please specify alias name and command".to_string(),
    246                    ));
    247                }
    248                let alias_name = &args[0];
    249                let command = args[1..].join(" ");
    250 
    251                Ok(ChatOpResult::Message(format!("✅ Created alias '{}' -> '{}' (feature requires persistent storage implementation)", alias_name, command)))
    252            }
    253        }
    254    }
    255 }