huskies: merge 644_story_chat_transport_consumers_slack_discord_whatsapp_matrix_for_the_unified_status_broadcaster
This commit is contained in:
@@ -233,6 +233,42 @@ pub async fn run_bot(
|
|||||||
watcher_rx_auto,
|
watcher_rx_auto,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Subscribe to the status broadcaster if the matrix_status_consumer toggle is
|
||||||
|
// enabled (default: true). The subscriber formats each StatusEvent via the
|
||||||
|
// common formatter and sends the resulting text to all configured Matrix rooms.
|
||||||
|
// The task exits automatically when the broadcaster is dropped (channel closed)
|
||||||
|
// on bot shutdown.
|
||||||
|
{
|
||||||
|
use crate::config::ProjectConfig;
|
||||||
|
use crate::service::status::format::format_status_event;
|
||||||
|
|
||||||
|
let status_enabled = ProjectConfig::load(project_root)
|
||||||
|
.map(|c| c.matrix_status_consumer)
|
||||||
|
.unwrap_or(true);
|
||||||
|
|
||||||
|
if status_enabled {
|
||||||
|
let mut sub = services.status.subscribe();
|
||||||
|
let status_transport = Arc::clone(&transport);
|
||||||
|
let status_rooms: Vec<String> =
|
||||||
|
announce_room_ids.iter().map(|r| r.to_string()).collect();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
while let Some(event) = sub.recv().await {
|
||||||
|
let plain = format_status_event(&event);
|
||||||
|
let html = markdown_to_html(&plain);
|
||||||
|
for room_id in &status_rooms {
|
||||||
|
if let Err(e) = status_transport.send_message(room_id, &plain, &html).await
|
||||||
|
{
|
||||||
|
crate::slog!(
|
||||||
|
"[matrix-bot] Failed to send status event to {room_id}: {e}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crate::slog!("[matrix-bot] Status subscriber task exiting — broadcaster dropped");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let ctx = BotContext {
|
let ctx = BotContext {
|
||||||
services,
|
services,
|
||||||
matrix_user_id: bot_user_id,
|
matrix_user_id: bot_user_id,
|
||||||
|
|||||||
@@ -49,6 +49,13 @@ pub struct ProjectConfig {
|
|||||||
/// Default: `true`.
|
/// Default: `true`.
|
||||||
#[serde(default = "default_web_ui_status_consumer")]
|
#[serde(default = "default_web_ui_status_consumer")]
|
||||||
pub web_ui_status_consumer: bool,
|
pub web_ui_status_consumer: bool,
|
||||||
|
/// Whether the Matrix bot subscribes to the status broadcaster and forwards
|
||||||
|
/// pipeline events to its configured rooms.
|
||||||
|
/// Set to `false` to silence Matrix status notifications without affecting
|
||||||
|
/// other consumers (web UI, Slack, Discord, WhatsApp, agent context).
|
||||||
|
/// Default: `true`.
|
||||||
|
#[serde(default = "default_matrix_status_consumer")]
|
||||||
|
pub matrix_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.
|
||||||
@@ -133,6 +140,10 @@ fn default_web_ui_status_consumer() -> bool {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_matrix_status_consumer() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn default_max_mesh_peers() -> usize {
|
fn default_max_mesh_peers() -> usize {
|
||||||
3
|
3
|
||||||
}
|
}
|
||||||
@@ -263,6 +274,7 @@ impl Default for ProjectConfig {
|
|||||||
base_branch: None,
|
base_branch: None,
|
||||||
rate_limit_notifications: default_rate_limit_notifications(),
|
rate_limit_notifications: default_rate_limit_notifications(),
|
||||||
web_ui_status_consumer: default_web_ui_status_consumer(),
|
web_ui_status_consumer: default_web_ui_status_consumer(),
|
||||||
|
matrix_status_consumer: default_matrix_status_consumer(),
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -345,6 +357,7 @@ impl ProjectConfig {
|
|||||||
base_branch: legacy.base_branch,
|
base_branch: legacy.base_branch,
|
||||||
rate_limit_notifications: legacy.rate_limit_notifications,
|
rate_limit_notifications: legacy.rate_limit_notifications,
|
||||||
web_ui_status_consumer: default_web_ui_status_consumer(),
|
web_ui_status_consumer: default_web_ui_status_consumer(),
|
||||||
|
matrix_status_consumer: default_matrix_status_consumer(),
|
||||||
timezone: legacy.timezone,
|
timezone: legacy.timezone,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -378,6 +391,7 @@ impl ProjectConfig {
|
|||||||
base_branch: legacy.base_branch,
|
base_branch: legacy.base_branch,
|
||||||
rate_limit_notifications: legacy.rate_limit_notifications,
|
rate_limit_notifications: legacy.rate_limit_notifications,
|
||||||
web_ui_status_consumer: default_web_ui_status_consumer(),
|
web_ui_status_consumer: default_web_ui_status_consumer(),
|
||||||
|
matrix_status_consumer: default_matrix_status_consumer(),
|
||||||
timezone: legacy.timezone,
|
timezone: legacy.timezone,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -399,6 +413,7 @@ impl ProjectConfig {
|
|||||||
base_branch: legacy.base_branch,
|
base_branch: legacy.base_branch,
|
||||||
rate_limit_notifications: legacy.rate_limit_notifications,
|
rate_limit_notifications: legacy.rate_limit_notifications,
|
||||||
web_ui_status_consumer: default_web_ui_status_consumer(),
|
web_ui_status_consumer: default_web_ui_status_consumer(),
|
||||||
|
matrix_status_consumer: default_matrix_status_consumer(),
|
||||||
timezone: legacy.timezone,
|
timezone: legacy.timezone,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
|
|||||||
@@ -529,6 +529,7 @@ mod tests {
|
|||||||
base_branch: None,
|
base_branch: None,
|
||||||
rate_limit_notifications: true,
|
rate_limit_notifications: true,
|
||||||
web_ui_status_consumer: true,
|
web_ui_status_consumer: true,
|
||||||
|
matrix_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -559,6 +560,7 @@ mod tests {
|
|||||||
base_branch: None,
|
base_branch: None,
|
||||||
rate_limit_notifications: true,
|
rate_limit_notifications: true,
|
||||||
web_ui_status_consumer: true,
|
web_ui_status_consumer: true,
|
||||||
|
matrix_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -589,6 +591,7 @@ mod tests {
|
|||||||
base_branch: None,
|
base_branch: None,
|
||||||
rate_limit_notifications: true,
|
rate_limit_notifications: true,
|
||||||
web_ui_status_consumer: true,
|
web_ui_status_consumer: true,
|
||||||
|
matrix_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -619,6 +622,7 @@ mod tests {
|
|||||||
base_branch: None,
|
base_branch: None,
|
||||||
rate_limit_notifications: true,
|
rate_limit_notifications: true,
|
||||||
web_ui_status_consumer: true,
|
web_ui_status_consumer: true,
|
||||||
|
matrix_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -648,6 +652,7 @@ mod tests {
|
|||||||
base_branch: None,
|
base_branch: None,
|
||||||
rate_limit_notifications: true,
|
rate_limit_notifications: true,
|
||||||
web_ui_status_consumer: true,
|
web_ui_status_consumer: true,
|
||||||
|
matrix_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -684,6 +689,7 @@ mod tests {
|
|||||||
base_branch: None,
|
base_branch: None,
|
||||||
rate_limit_notifications: true,
|
rate_limit_notifications: true,
|
||||||
web_ui_status_consumer: true,
|
web_ui_status_consumer: true,
|
||||||
|
matrix_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -761,6 +767,7 @@ mod tests {
|
|||||||
base_branch: None,
|
base_branch: None,
|
||||||
rate_limit_notifications: true,
|
rate_limit_notifications: true,
|
||||||
web_ui_status_consumer: true,
|
web_ui_status_consumer: true,
|
||||||
|
matrix_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -796,6 +803,7 @@ mod tests {
|
|||||||
base_branch: None,
|
base_branch: None,
|
||||||
rate_limit_notifications: true,
|
rate_limit_notifications: true,
|
||||||
web_ui_status_consumer: true,
|
web_ui_status_consumer: true,
|
||||||
|
matrix_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -878,6 +886,7 @@ mod tests {
|
|||||||
base_branch: None,
|
base_branch: None,
|
||||||
rate_limit_notifications: true,
|
rate_limit_notifications: true,
|
||||||
web_ui_status_consumer: true,
|
web_ui_status_consumer: true,
|
||||||
|
matrix_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -916,6 +925,7 @@ mod tests {
|
|||||||
base_branch: None,
|
base_branch: None,
|
||||||
rate_limit_notifications: true,
|
rate_limit_notifications: true,
|
||||||
web_ui_status_consumer: true,
|
web_ui_status_consumer: true,
|
||||||
|
matrix_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -944,6 +954,7 @@ mod tests {
|
|||||||
base_branch: None,
|
base_branch: None,
|
||||||
rate_limit_notifications: true,
|
rate_limit_notifications: true,
|
||||||
web_ui_status_consumer: true,
|
web_ui_status_consumer: true,
|
||||||
|
matrix_status_consumer: true,
|
||||||
timezone: None,
|
timezone: None,
|
||||||
rendezvous: None,
|
rendezvous: None,
|
||||||
trusted_keys: Vec::new(),
|
trusted_keys: Vec::new(),
|
||||||
@@ -978,6 +989,7 @@ mod tests {
|
|||||||
base_branch: None,
|
base_branch: None,
|
||||||
rate_limit_notifications: true,
|
rate_limit_notifications: true,
|
||||||
web_ui_status_consumer: true,
|
web_ui_status_consumer: true,
|
||||||
|
matrix_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