feat(channel): add mention_only option for Telegram groups

Adds mention_only config option to Telegram channel, allowing the bot
to only respond to messages that @-mention the bot in group chats.
Direct messages are always processed regardless of this setting.

Behavior:
- When mention_only = true: Bot only responds to group messages containing @botname
- When mention_only = false (default): Bot responds to all allowed messages
- DM/private chats always work regardless of mention_only setting

Implementation:
- Fetch and cache bot username from Telegram API on startup
- Check for @botname mention in group messages
- Strip mention from message content before processing

Config example:
[channels.telegram]
bot_token = "your_token"
mention_only = true

Changes:
- src/config/schema.rs: Add mention_only to TelegramConfig
- src/channels/telegram.rs: Implement mention_only logic + 6 new tests
- src/channels/mod.rs: Update factory calls
- src/cron/scheduler.rs: Update constructor call
- src/onboard/wizard.rs: Update wizard config
- src/daemon/mod.rs: Update test config
- src/integrations/registry.rs: Update test config
- TESTING_TELEGRAM.md: Add mention_only test section
- CHANGELOG.md: Document feature

Risk: medium
Backward compatible: Yes (default: false)
This commit is contained in:
ZeroClaw Contributor 2026-02-18 12:57:38 +03:00 committed by Chummy
parent 3b75c6cc42
commit c0a80ad656
10 changed files with 264 additions and 54 deletions

View file

@ -1465,6 +1465,10 @@ pub struct TelegramConfig {
/// Minimum interval (ms) between draft message edits to avoid rate limits.
#[serde(default = "default_draft_update_interval_ms")]
pub draft_update_interval_ms: u64,
/// When true, only respond to messages that @-mention the bot in groups.
/// Direct messages are always processed.
#[serde(default)]
pub mention_only: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -2535,6 +2539,7 @@ default_temperature = 0.7
allowed_users: vec!["user1".into()],
stream_mode: StreamMode::default(),
draft_update_interval_ms: default_draft_update_interval_ms(),
mention_only: false,
}),
discord: None,
slack: None,
@ -2808,6 +2813,7 @@ tool_dispatcher = "xml"
allowed_users: vec!["alice".into(), "bob".into()],
stream_mode: StreamMode::Partial,
draft_update_interval_ms: 500,
mention_only: false,
};
let json = serde_json::to_string(&tc).unwrap();
let parsed: TelegramConfig = serde_json::from_str(&json).unwrap();