diff --git a/src/channels/mod.rs b/src/channels/mod.rs index a214d0c..b48479b 100644 --- a/src/channels/mod.rs +++ b/src/channels/mod.rs @@ -563,6 +563,46 @@ fn inject_workspace_file( } } +fn normalize_telegram_identity(value: &str) -> String { + value.trim().trim_start_matches('@').to_string() +} + +fn bind_telegram_identity(config: &Config, identity: &str) -> Result<()> { + let normalized = normalize_telegram_identity(identity); + if normalized.is_empty() { + anyhow::bail!("Telegram identity cannot be empty"); + } + + let mut updated = config.clone(); + let Some(telegram) = updated.channels_config.telegram.as_mut() else { + anyhow::bail!( + "Telegram channel is not configured. Run `zeroclaw onboard --channels-only` first" + ); + }; + + if telegram.allowed_users.iter().any(|u| u == "*") { + println!( + "⚠️ Telegram allowlist is currently wildcard (`*`) — binding is unnecessary until you remove '*'." + ); + } + + if telegram + .allowed_users + .iter() + .map(|entry| normalize_telegram_identity(entry)) + .any(|entry| entry == normalized) + { + println!("✅ Telegram identity already bound: {normalized}"); + return Ok(()); + } + + telegram.allowed_users.push(normalized.clone()); + updated.save()?; + println!("✅ Bound Telegram identity: {normalized}"); + println!(" Saved to {}", updated.config_path.display()); + Ok(()) +} + pub fn handle_command(command: crate::ChannelCommands, config: &Config) -> Result<()> { match command { crate::ChannelCommands::Start => { @@ -606,6 +646,9 @@ pub fn handle_command(command: crate::ChannelCommands, config: &Config) -> Resul crate::ChannelCommands::Remove { name } => { anyhow::bail!("Remove channel '{name}' — edit ~/.zeroclaw/config.toml directly"); } + crate::ChannelCommands::BindTelegram { identity } => { + bind_telegram_identity(config, &identity) + } } } diff --git a/src/lib.rs b/src/lib.rs index 7f4ebb4..726d756 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -104,6 +104,11 @@ pub enum ChannelCommands { /// Channel name to remove name: String, }, + /// Bind a Telegram identity (username or numeric user ID) into allowlist + BindTelegram { + /// Telegram identity to allow (username without '@' or numeric user ID) + identity: String, + }, } /// Skills management subcommands diff --git a/src/main.rs b/src/main.rs index 56cd579..ecb5fb0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -328,6 +328,11 @@ enum ChannelCommands { /// Channel name name: String, }, + /// Bind a Telegram identity (username or numeric user ID) into allowlist + BindTelegram { + /// Telegram identity to allow (username without '@' or numeric user ID) + identity: String, + }, } #[derive(Subcommand, Debug)]