registry.rs (3742B)
1 use crate::chatops::{ChatCommand, ChatOpError, ChatOpResult, CommandContext, UserRole}; 2 use std::collections::HashMap; 3 4 /// Registry for managing ChatOps commands 5 pub struct CommandRegistry { 6 commands: HashMap<String, Box<dyn ChatCommand>>, 7 aliases: HashMap<String, String>, 8 } 9 10 impl CommandRegistry { 11 pub fn new() -> Self { 12 Self { 13 commands: HashMap::new(), 14 aliases: HashMap::new(), 15 } 16 } 17 18 /// Register a new command 19 pub fn register(&mut self, command: Box<dyn ChatCommand>) { 20 let name = command.name().to_string(); 21 22 // Register aliases 23 for alias in command.aliases() { 24 self.aliases.insert(alias.to_string(), name.clone()); 25 } 26 27 self.commands.insert(name, command); 28 } 29 30 /// Get command by name or alias 31 pub fn get_command(&self, name: &str) -> Option<&dyn ChatCommand> { 32 let actual_name = name.to_string(); 33 let command_name = self.aliases.get(name).unwrap_or(&actual_name); 34 self.commands.get(command_name).map(|cmd| cmd.as_ref()) 35 } 36 37 /// Execute a command with arguments 38 pub fn execute_command( 39 &self, 40 name: &str, 41 args: Vec<String>, 42 context: &CommandContext, 43 ) -> Result<ChatOpResult, ChatOpError> { 44 match self.get_command(name) { 45 Some(command) => { 46 // Check permissions 47 if !self.check_permission(&context.role, &command.required_role()) { 48 return Err(ChatOpError::PermissionDenied(format!( 49 "Command '{}' requires {:?} role or higher", 50 name, 51 command.required_role() 52 ))); 53 } 54 55 command.execute(args, context) 56 } 57 None => Err(ChatOpError::Generic(format!("Unknown command: {}", name))), 58 } 59 } 60 61 /// List all available commands for a user role 62 pub fn list_commands(&self, role: &UserRole) -> Vec<(&str, &str)> { 63 self.commands 64 .values() 65 .filter(|cmd| self.check_permission(role, &cmd.required_role())) 66 .map(|cmd| (cmd.name(), cmd.description())) 67 .collect() 68 } 69 70 /// Get help for a specific command 71 pub fn get_help(&self, name: &str) -> Option<String> { 72 self.get_command(name).map(|cmd| { 73 format!( 74 "**{}** - {}\n\nUsage: {}\n\nAliases: {}", 75 cmd.name(), 76 cmd.description(), 77 cmd.usage(), 78 if cmd.aliases().is_empty() { 79 "none".to_string() 80 } else { 81 cmd.aliases().join(", ") 82 } 83 ) 84 }) 85 } 86 87 /// Check if user role has permission for required role 88 fn check_permission(&self, user_role: &UserRole, required_role: &UserRole) -> bool { 89 let user_level = self.role_level(user_role); 90 let required_level = self.role_level(required_role); 91 user_level >= required_level 92 } 93 94 /// Convert role to numeric level for comparison 95 fn role_level(&self, role: &UserRole) -> u8 { 96 match role { 97 UserRole::Guest => 0, 98 UserRole::Member => 1, 99 UserRole::Staff => 2, 100 UserRole::Admin => 3, 101 } 102 } 103 104 /// Register a user alias for a command 105 #[allow(dead_code)] 106 pub fn register_alias(&mut self, alias: String, target: String) { 107 if self.commands.contains_key(&target) { 108 self.aliases.insert(alias, target); 109 } 110 } 111 112 /// Remove a user alias 113 #[allow(dead_code)] 114 pub fn remove_alias(&mut self, alias: &str) { 115 self.aliases.remove(alias); 116 } 117 }