group-aware messaging
* reply in group if admin command from group * allow alerts to be sent to a group instead of individual admins
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
alertmanager::AlertPost,
|
||||
jsonrpc::{Envelope, RpcClient, RpcClientError, SignalMessage, connect_tcp},
|
||||
jsonrpc::{Envelope, MessageTarget, RpcClient, RpcClientError, SignalMessage, connect_tcp},
|
||||
log_message::{LogMessage, Origin},
|
||||
message_handler::{AdminMessageResponse, MessageHandler, MessageHandlerResult},
|
||||
prometheus::{Prometheus, PrometheusConfig},
|
||||
@@ -52,6 +52,9 @@ pub struct GatewayConfig {
|
||||
pub signal_account: String,
|
||||
#[conf(repeat, long, env)]
|
||||
pub admin_uuid: Vec<String>,
|
||||
/// If set, alerts are sent to this group instead of individual admins
|
||||
#[conf(long, env)]
|
||||
pub alert_group_id: Option<String>,
|
||||
#[conf(flatten)]
|
||||
pub prometheus: Option<PrometheusConfig>,
|
||||
#[conf(flatten)]
|
||||
@@ -256,9 +259,15 @@ impl Gateway {
|
||||
msg.text
|
||||
};
|
||||
let attachments = msg.attachment_paths.into_iter().map(|p| p.to_str().unwrap().to_owned()).collect();
|
||||
// Send to group if configured, otherwise to individual admins
|
||||
let target = if let Some(group_id) = &self.config.alert_group_id {
|
||||
MessageTarget::Group(group_id.clone())
|
||||
} else {
|
||||
MessageTarget::Recipients(self.config.admin_uuid.clone())
|
||||
};
|
||||
SignalMessage {
|
||||
sender: self.config.signal_account.clone(),
|
||||
recipient: self.config.admin_uuid.clone(),
|
||||
target,
|
||||
message,
|
||||
attachments,
|
||||
}.send(signal_cli).await?;
|
||||
@@ -280,11 +289,16 @@ impl Gateway {
|
||||
}
|
||||
Some(Ok(msg)) => {
|
||||
//info!("Signal Rx: {msg:?}");
|
||||
if msg.envelope.data_message.is_none() {
|
||||
let Some(data_message) = &msg.envelope.data_message else {
|
||||
debug!("Ignoring message which was not a data message: {msg:?}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// Determine if this message came from a group
|
||||
let from_group = data_message.group_info.as_ref().map(|g| g.group_id.clone());
|
||||
|
||||
// For group messages, check if sender is an admin
|
||||
// For direct messages, check if sender is an admin
|
||||
if !self.config.admin_uuid.contains(&msg.envelope.source_uuid) {
|
||||
warn!("Ignoring message from non-admin: {msg:?}");
|
||||
continue;
|
||||
@@ -307,9 +321,16 @@ impl Gateway {
|
||||
|
||||
let attachments = resp.attachments.into_iter().map(|p| p.to_str().expect("attachments must have utf8 paths").to_owned()).collect();
|
||||
|
||||
// Reply to group if message came from a group, otherwise reply to sender
|
||||
let target = if let Some(group_id) = from_group {
|
||||
MessageTarget::Group(group_id)
|
||||
} else {
|
||||
MessageTarget::Recipients(vec![msg.envelope.source_uuid.clone()])
|
||||
};
|
||||
|
||||
SignalMessage {
|
||||
sender: self.config.signal_account.clone(),
|
||||
recipient: vec![msg.envelope.source_uuid.clone()],
|
||||
target,
|
||||
message: resp.text,
|
||||
attachments,
|
||||
}.send(signal_cli).await?;
|
||||
|
||||
@@ -430,6 +430,14 @@ pub struct Envelope {
|
||||
pub struct DataMessage {
|
||||
pub timestamp: u64,
|
||||
pub message: String,
|
||||
#[serde(default)]
|
||||
pub group_info: Option<GroupInfo>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GroupInfo {
|
||||
pub group_id: String,
|
||||
}
|
||||
|
||||
/// Connect to signal-cli over tcp socket
|
||||
@@ -472,10 +480,19 @@ impl Envelope {
|
||||
}
|
||||
}
|
||||
|
||||
/// Target for a SignalMessage - either individual recipients or a group
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum MessageTarget {
|
||||
/// Send to individual recipients
|
||||
Recipients(Vec<String>),
|
||||
/// Send to a group
|
||||
Group(String),
|
||||
}
|
||||
|
||||
/// Helper for invoking send, which has way too many parameters
|
||||
pub struct SignalMessage {
|
||||
pub sender: String,
|
||||
pub recipient: Vec<String>,
|
||||
pub target: MessageTarget,
|
||||
pub message: String,
|
||||
pub attachments: Vec<String>,
|
||||
}
|
||||
@@ -512,8 +529,10 @@ impl SignalMessage {
|
||||
editTimestamp: Option<u64>,
|
||||
*/
|
||||
let account = Some(self.sender);
|
||||
let recipients = self.recipient;
|
||||
let groupIds = vec![];
|
||||
let (recipients, groupIds) = match self.target {
|
||||
MessageTarget::Recipients(r) => (r, vec![]),
|
||||
MessageTarget::Group(g) => (vec![], vec![g]),
|
||||
};
|
||||
let noteToSelf = false;
|
||||
let endSession = false;
|
||||
let message = self.message;
|
||||
|
||||
Reference in New Issue
Block a user