feat(telegram): add operator bind command for unauthorized users

This commit is contained in:
leon 2026-02-17 06:46:56 -05:00 committed by Chummy
parent bfc67c9c29
commit fa94117269
3 changed files with 53 additions and 0 deletions

View file

@ -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<()> { pub fn handle_command(command: crate::ChannelCommands, config: &Config) -> Result<()> {
match command { match command {
crate::ChannelCommands::Start => { crate::ChannelCommands::Start => {
@ -606,6 +646,9 @@ pub fn handle_command(command: crate::ChannelCommands, config: &Config) -> Resul
crate::ChannelCommands::Remove { name } => { crate::ChannelCommands::Remove { name } => {
anyhow::bail!("Remove channel '{name}' — edit ~/.zeroclaw/config.toml directly"); anyhow::bail!("Remove channel '{name}' — edit ~/.zeroclaw/config.toml directly");
} }
crate::ChannelCommands::BindTelegram { identity } => {
bind_telegram_identity(config, &identity)
}
} }
} }

View file

@ -104,6 +104,11 @@ pub enum ChannelCommands {
/// Channel name to remove /// Channel name to remove
name: String, 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 /// Skills management subcommands

View file

@ -328,6 +328,11 @@ enum ChannelCommands {
/// Channel name /// Channel name
name: String, 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)] #[derive(Subcommand, Debug)]