feat: Add full WhatsApp Business Cloud API integration
- Add WhatsApp channel module with Cloud API v18.0 support - Implement webhook-based message reception and API sending - Add allowlist for phone numbers (E.164 format or wildcard) - Add WhatsApp webhook endpoints to gateway (/whatsapp GET/POST) - Add WhatsApp config schema with TOML support - Wire WhatsApp into channel factory, CLI, and doctor commands - Add WhatsApp to setup wizard with connection testing - Add comprehensive test coverage (47 channel tests + 9 URL decoding tests) - Update README with detailed WhatsApp setup instructions - Support text messages only, skip media/status updates - Normalize phone numbers with + prefix - Handle webhook verification with Meta challenge-response All 756 tests pass. Ready for production use.
This commit is contained in:
parent
ec2d5cc93d
commit
cc08f4bfff
6 changed files with 1749 additions and 5 deletions
|
|
@ -5,6 +5,7 @@ pub mod matrix;
|
|||
pub mod slack;
|
||||
pub mod telegram;
|
||||
pub mod traits;
|
||||
pub mod whatsapp;
|
||||
|
||||
pub use cli::CliChannel;
|
||||
pub use discord::DiscordChannel;
|
||||
|
|
@ -13,6 +14,7 @@ pub use matrix::MatrixChannel;
|
|||
pub use slack::SlackChannel;
|
||||
pub use telegram::TelegramChannel;
|
||||
pub use traits::Channel;
|
||||
pub use whatsapp::WhatsAppChannel;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::memory::{self, Memory};
|
||||
|
|
@ -236,6 +238,7 @@ pub fn handle_command(command: super::ChannelCommands, config: &Config) -> Resul
|
|||
("Webhook", config.channels_config.webhook.is_some()),
|
||||
("iMessage", config.channels_config.imessage.is_some()),
|
||||
("Matrix", config.channels_config.matrix.is_some()),
|
||||
("WhatsApp", config.channels_config.whatsapp.is_some()),
|
||||
] {
|
||||
println!(" {} {name}", if configured { "✅" } else { "❌" });
|
||||
}
|
||||
|
|
@ -330,6 +333,18 @@ pub async fn doctor_channels(config: Config) -> Result<()> {
|
|||
));
|
||||
}
|
||||
|
||||
if let Some(ref wa) = config.channels_config.whatsapp {
|
||||
channels.push((
|
||||
"WhatsApp",
|
||||
Arc::new(WhatsAppChannel::new(
|
||||
wa.access_token.clone(),
|
||||
wa.phone_number_id.clone(),
|
||||
wa.verify_token.clone(),
|
||||
wa.allowed_numbers.clone(),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
if channels.is_empty() {
|
||||
println!("No real-time channels configured. Run `zeroclaw onboard` first.");
|
||||
return Ok(());
|
||||
|
|
@ -481,6 +496,15 @@ pub async fn start_channels(config: Config) -> Result<()> {
|
|||
)));
|
||||
}
|
||||
|
||||
if let Some(ref wa) = config.channels_config.whatsapp {
|
||||
channels.push(Arc::new(WhatsAppChannel::new(
|
||||
wa.access_token.clone(),
|
||||
wa.phone_number_id.clone(),
|
||||
wa.verify_token.clone(),
|
||||
wa.allowed_numbers.clone(),
|
||||
)));
|
||||
}
|
||||
|
||||
if channels.is_empty() {
|
||||
println!("No channels configured. Run `zeroclaw onboard` to set up channels.");
|
||||
return Ok(());
|
||||
|
|
|
|||
1223
src/channels/whatsapp.rs
Normal file
1223
src/channels/whatsapp.rs
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue