huskies: merge 649_story_migrate_whatsapp_transport_to_status_broadcaster
This commit is contained in:
@@ -70,6 +70,13 @@ pub struct ProjectConfig {
|
|||||||
/// Default: `true`.
|
/// Default: `true`.
|
||||||
#[serde(default = "default_discord_status_consumer")]
|
#[serde(default = "default_discord_status_consumer")]
|
||||||
pub discord_status_consumer: bool,
|
pub discord_status_consumer: bool,
|
||||||
|
/// Whether the WhatsApp bot subscribes to the status broadcaster and forwards
|
||||||
|
/// pipeline events to all active senders.
|
||||||
|
/// Set to `false` to silence WhatsApp status notifications without affecting
|
||||||
|
/// other consumers (web UI, Matrix, Slack, Discord, agent context).
|
||||||
|
/// Default: `true`.
|
||||||
|
#[serde(default = "default_whatsapp_status_consumer")]
|
||||||
|
pub whatsapp_status_consumer: bool,
|
||||||
/// IANA timezone name (e.g. `"Europe/London"`, `"America/New_York"`).
|
/// IANA timezone name (e.g. `"Europe/London"`, `"America/New_York"`).
|
||||||
/// When set, timer HH:MM inputs are interpreted in this timezone instead
|
/// When set, timer HH:MM inputs are interpreted in this timezone instead
|
||||||
/// of the container/host local time. Falls back to `chrono::Local` when absent.
|
/// of the container/host local time. Falls back to `chrono::Local` when absent.
|
||||||
@@ -166,6 +173,10 @@ fn default_discord_status_consumer() -> bool {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_whatsapp_status_consumer() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn default_max_mesh_peers() -> usize {
|
fn default_max_mesh_peers() -> usize {
|
||||||
3
|
3
|
||||||
}
|
}
|
||||||
@@ -299,6 +310,7 @@ impl Default for ProjectConfig {
|
|||||||
matrix_status_consumer: default_matrix_status_consumer(),
|
matrix_status_consumer: default_matrix_status_consumer(),
|
||||||
slack_status_consumer: default_slack_status_consumer(),
|
slack_status_consumer: default_slack_status_consumer(),
|
||||||
discord_status_consumer: default_discord_status_consumer(),
|
discord_status_consumer: default_discord_status_consumer(),
|
||||||
|
whatsapp_status_consumer: default_whatsapp_status_consumer(),
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -384,6 +396,7 @@ impl ProjectConfig {
|
|||||||
matrix_status_consumer: default_matrix_status_consumer(),
|
matrix_status_consumer: default_matrix_status_consumer(),
|
||||||
slack_status_consumer: default_slack_status_consumer(),
|
slack_status_consumer: default_slack_status_consumer(),
|
||||||
discord_status_consumer: default_discord_status_consumer(),
|
discord_status_consumer: default_discord_status_consumer(),
|
||||||
|
whatsapp_status_consumer: default_whatsapp_status_consumer(),
|
||||||
timezone: legacy.timezone,
|
timezone: legacy.timezone,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -420,6 +433,7 @@ impl ProjectConfig {
|
|||||||
matrix_status_consumer: default_matrix_status_consumer(),
|
matrix_status_consumer: default_matrix_status_consumer(),
|
||||||
slack_status_consumer: default_slack_status_consumer(),
|
slack_status_consumer: default_slack_status_consumer(),
|
||||||
discord_status_consumer: default_discord_status_consumer(),
|
discord_status_consumer: default_discord_status_consumer(),
|
||||||
|
whatsapp_status_consumer: default_whatsapp_status_consumer(),
|
||||||
timezone: legacy.timezone,
|
timezone: legacy.timezone,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -444,6 +458,7 @@ impl ProjectConfig {
|
|||||||
matrix_status_consumer: default_matrix_status_consumer(),
|
matrix_status_consumer: default_matrix_status_consumer(),
|
||||||
slack_status_consumer: default_slack_status_consumer(),
|
slack_status_consumer: default_slack_status_consumer(),
|
||||||
discord_status_consumer: default_discord_status_consumer(),
|
discord_status_consumer: default_discord_status_consumer(),
|
||||||
|
whatsapp_status_consumer: default_whatsapp_status_consumer(),
|
||||||
timezone: legacy.timezone,
|
timezone: legacy.timezone,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
|
|||||||
@@ -752,6 +752,39 @@ async fn main() -> Result<(), std::io::Error> {
|
|||||||
watcher_rx_for_whatsapp,
|
watcher_rx_for_whatsapp,
|
||||||
root.clone(),
|
root.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Subscribe to the status broadcaster if the whatsapp_status_consumer toggle
|
||||||
|
// is enabled (default: true). Formats each StatusEvent via the common
|
||||||
|
// formatter and sends the resulting text to all active WhatsApp senders.
|
||||||
|
// The task exits automatically when the broadcaster is dropped on shutdown.
|
||||||
|
{
|
||||||
|
use crate::service::status::format::format_status_event;
|
||||||
|
|
||||||
|
let status_enabled = config::ProjectConfig::load(root)
|
||||||
|
.map(|c| c.whatsapp_status_consumer)
|
||||||
|
.unwrap_or(true);
|
||||||
|
|
||||||
|
if status_enabled {
|
||||||
|
let mut sub = ctx.services.status.subscribe();
|
||||||
|
let transport = Arc::clone(&ctx.transport) as Arc<dyn crate::chat::ChatTransport>;
|
||||||
|
let ambient_rooms = Arc::clone(&ctx.services.ambient_rooms);
|
||||||
|
tokio::spawn(async move {
|
||||||
|
while let Some(event) = sub.recv().await {
|
||||||
|
let plain = format_status_event(&event);
|
||||||
|
let rooms: Vec<String> =
|
||||||
|
ambient_rooms.lock().unwrap().iter().cloned().collect();
|
||||||
|
for room in &rooms {
|
||||||
|
if let Err(e) = transport.send_message(room, &plain, "").await {
|
||||||
|
crate::slog!(
|
||||||
|
"[whatsapp] Failed to send status event to {room}: {e}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crate::slog!("[whatsapp] Status subscriber task exiting — broadcaster dropped");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
drop(watcher_rx_for_whatsapp);
|
drop(watcher_rx_for_whatsapp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -532,6 +532,7 @@ mod tests {
|
|||||||
matrix_status_consumer: true,
|
matrix_status_consumer: true,
|
||||||
slack_status_consumer: true,
|
slack_status_consumer: true,
|
||||||
discord_status_consumer: true,
|
discord_status_consumer: true,
|
||||||
|
whatsapp_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -565,6 +566,7 @@ mod tests {
|
|||||||
matrix_status_consumer: true,
|
matrix_status_consumer: true,
|
||||||
slack_status_consumer: true,
|
slack_status_consumer: true,
|
||||||
discord_status_consumer: true,
|
discord_status_consumer: true,
|
||||||
|
whatsapp_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -598,6 +600,7 @@ mod tests {
|
|||||||
matrix_status_consumer: true,
|
matrix_status_consumer: true,
|
||||||
slack_status_consumer: true,
|
slack_status_consumer: true,
|
||||||
discord_status_consumer: true,
|
discord_status_consumer: true,
|
||||||
|
whatsapp_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -631,6 +634,7 @@ mod tests {
|
|||||||
matrix_status_consumer: true,
|
matrix_status_consumer: true,
|
||||||
slack_status_consumer: true,
|
slack_status_consumer: true,
|
||||||
discord_status_consumer: true,
|
discord_status_consumer: true,
|
||||||
|
whatsapp_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -663,6 +667,7 @@ mod tests {
|
|||||||
matrix_status_consumer: true,
|
matrix_status_consumer: true,
|
||||||
slack_status_consumer: true,
|
slack_status_consumer: true,
|
||||||
discord_status_consumer: true,
|
discord_status_consumer: true,
|
||||||
|
whatsapp_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -702,6 +707,7 @@ mod tests {
|
|||||||
matrix_status_consumer: true,
|
matrix_status_consumer: true,
|
||||||
slack_status_consumer: true,
|
slack_status_consumer: true,
|
||||||
discord_status_consumer: true,
|
discord_status_consumer: true,
|
||||||
|
whatsapp_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -782,6 +788,7 @@ mod tests {
|
|||||||
matrix_status_consumer: true,
|
matrix_status_consumer: true,
|
||||||
slack_status_consumer: true,
|
slack_status_consumer: true,
|
||||||
discord_status_consumer: true,
|
discord_status_consumer: true,
|
||||||
|
whatsapp_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -820,6 +827,7 @@ mod tests {
|
|||||||
matrix_status_consumer: true,
|
matrix_status_consumer: true,
|
||||||
slack_status_consumer: true,
|
slack_status_consumer: true,
|
||||||
discord_status_consumer: true,
|
discord_status_consumer: true,
|
||||||
|
whatsapp_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -905,6 +913,7 @@ mod tests {
|
|||||||
matrix_status_consumer: true,
|
matrix_status_consumer: true,
|
||||||
slack_status_consumer: true,
|
slack_status_consumer: true,
|
||||||
discord_status_consumer: true,
|
discord_status_consumer: true,
|
||||||
|
whatsapp_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -946,6 +955,7 @@ mod tests {
|
|||||||
matrix_status_consumer: true,
|
matrix_status_consumer: true,
|
||||||
slack_status_consumer: true,
|
slack_status_consumer: true,
|
||||||
discord_status_consumer: true,
|
discord_status_consumer: true,
|
||||||
|
whatsapp_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -977,6 +987,7 @@ mod tests {
|
|||||||
matrix_status_consumer: true,
|
matrix_status_consumer: true,
|
||||||
slack_status_consumer: true,
|
slack_status_consumer: true,
|
||||||
discord_status_consumer: true,
|
discord_status_consumer: true,
|
||||||
|
whatsapp_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -1014,6 +1025,7 @@ mod tests {
|
|||||||
matrix_status_consumer: true,
|
matrix_status_consumer: true,
|
||||||
slack_status_consumer: true,
|
slack_status_consumer: true,
|
||||||
discord_status_consumer: true,
|
discord_status_consumer: true,
|
||||||
|
whatsapp_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
|
|||||||
Reference in New Issue
Block a user