feat(channels): add Lark/Feishu IM channel support
Implement Lark/Feishu as a new channel for ZeroClaw (Issue #164). - Add LarkChannel with Channel trait impl (name, listen, send) - listen: HTTP server (axum) for event callback with URL verification (challenge response) and im.message.receive_v1 text message parsing - send: POST /open-apis/im/v1/messages with tenant_access_token auth - get_tenant_access_token with caching and auto-refresh on 401 - Allowlist filtering by open_id (same pattern as other channels) - Add LarkConfig to schema (app_id, app_secret, verification_token, port, allowed_users) - Register lark in channel list, doctor, and start_channels - 18 unit tests: config serde, allowlist, channel name, message parsing, edge cases (unicode, missing fields, invalid JSON, wrong event type) - Fix pre-existing SchedulerConfig compile error on main
This commit is contained in:
parent
f0373f2db1
commit
760728d038
2 changed files with 675 additions and 0 deletions
|
|
@ -3,6 +3,7 @@ pub mod discord;
|
|||
pub mod email_channel;
|
||||
pub mod imessage;
|
||||
pub mod irc;
|
||||
pub mod lark;
|
||||
pub mod matrix;
|
||||
pub mod slack;
|
||||
pub mod telegram;
|
||||
|
|
@ -14,6 +15,7 @@ pub use discord::DiscordChannel;
|
|||
pub use email_channel::EmailChannel;
|
||||
pub use imessage::IMessageChannel;
|
||||
pub use irc::IrcChannel;
|
||||
pub use lark::LarkChannel;
|
||||
pub use matrix::MatrixChannel;
|
||||
pub use slack::SlackChannel;
|
||||
pub use telegram::TelegramChannel;
|
||||
|
|
@ -506,6 +508,7 @@ pub fn handle_command(command: crate::ChannelCommands, config: &Config) -> Resul
|
|||
("WhatsApp", config.channels_config.whatsapp.is_some()),
|
||||
("Email", config.channels_config.email.is_some()),
|
||||
("IRC", config.channels_config.irc.is_some()),
|
||||
("Lark", config.channels_config.lark.is_some()),
|
||||
] {
|
||||
println!(" {} {name}", if configured { "✅" } else { "❌" });
|
||||
}
|
||||
|
|
@ -635,6 +638,19 @@ pub async fn doctor_channels(config: Config) -> Result<()> {
|
|||
));
|
||||
}
|
||||
|
||||
if let Some(ref lk) = config.channels_config.lark {
|
||||
channels.push((
|
||||
"Lark",
|
||||
Arc::new(LarkChannel::new(
|
||||
lk.app_id.clone(),
|
||||
lk.app_secret.clone(),
|
||||
lk.verification_token.clone().unwrap_or_default(),
|
||||
9898,
|
||||
lk.allowed_users.clone(),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
if channels.is_empty() {
|
||||
println!("No real-time channels configured. Run `zeroclaw onboard` first.");
|
||||
return Ok(());
|
||||
|
|
@ -871,6 +887,16 @@ pub async fn start_channels(config: Config) -> Result<()> {
|
|||
)));
|
||||
}
|
||||
|
||||
if let Some(ref lk) = config.channels_config.lark {
|
||||
channels.push(Arc::new(LarkChannel::new(
|
||||
lk.app_id.clone(),
|
||||
lk.app_secret.clone(),
|
||||
lk.verification_token.clone().unwrap_or_default(),
|
||||
9898,
|
||||
lk.allowed_users.clone(),
|
||||
)));
|
||||
}
|
||||
|
||||
if channels.is_empty() {
|
||||
println!("No channels configured. Run `zeroclaw onboard` to set up channels.");
|
||||
return Ok(());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue