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 }