Conduit is a simple, fast and reliable chat server powered by Matrix https://conduit.rs
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
5.2 KiB
148 lines
5.2 KiB
use crate::{Error, PduEvent, Result}; |
|
use ruma::{ |
|
api::client::r0::push::{Pusher, PusherKind}, |
|
events::{ |
|
room::{ |
|
member::MemberEventContent, |
|
message::{MessageEventContent, TextMessageEventContent}, |
|
}, |
|
EventType, |
|
}, |
|
push::{PushCondition, Ruleset}, |
|
UserId, |
|
}; |
|
|
|
#[derive(Debug, Clone)] |
|
pub struct PushData { |
|
/// UserId + pushkey -> Pusher |
|
pub(super) senderkey_pusher: sled::Tree, |
|
} |
|
|
|
impl PushData { |
|
pub fn new(db: &sled::Db) -> Result<Self> { |
|
Ok(Self { |
|
senderkey_pusher: db.open_tree("senderkey_pusher")?, |
|
}) |
|
} |
|
|
|
pub fn set_pusher(&self, sender: &UserId, pusher: Pusher) -> Result<()> { |
|
let mut key = sender.as_bytes().to_vec(); |
|
key.extend_from_slice(pusher.pushkey.as_bytes()); |
|
|
|
self.senderkey_pusher.insert( |
|
key, |
|
&*serde_json::to_string(&pusher).expect("Pusher is valid JSON string"), |
|
)?; |
|
|
|
Ok(()) |
|
} |
|
|
|
pub fn get_pusher(&self, sender: &UserId) -> Result<Vec<Pusher>> { |
|
self.senderkey_pusher |
|
.scan_prefix(sender.as_bytes()) |
|
.values() |
|
.map(|push: std::result::Result<sled::IVec, _>| { |
|
let push = push.map_err(|_| Error::bad_database("Invalid push bytes in db."))?; |
|
Ok(serde_json::from_slice(&*push) |
|
.map_err(|_| Error::bad_database("Invalid Pusher in db."))?) |
|
}) |
|
.collect::<Result<Vec<_>>>() |
|
} |
|
} |
|
|
|
pub async fn send_push_notice( |
|
user: &UserId, |
|
pusher: &Pusher, |
|
ruleset: Ruleset, |
|
pdu: &PduEvent, |
|
) -> Result<()> { |
|
for rule in ruleset.into_iter() { |
|
// TODO: can actions contain contradictory Actions |
|
if rule |
|
.actions |
|
.iter() |
|
.any(|act| matches!(act, ruma::push::Action::DontNotify)) |
|
|| !rule.enabled |
|
{ |
|
continue; |
|
} |
|
|
|
match rule.rule_id.as_str() { |
|
".m.rule.master" => {} |
|
".m.rule.suppress_notices" => {} |
|
".m.rule.invite_for_me" => {} |
|
".m.rule.member_event" => { |
|
if let EventType::RoomMember = &pdu.kind { |
|
// TODO use this? |
|
let _member = serde_json::from_value::<MemberEventContent>(pdu.content.clone()) |
|
.map_err(|_| Error::bad_database("PDU contained bad message content"))?; |
|
if let Some(conditions) = rule.conditions { |
|
if conditions.iter().any(|cond| match cond { |
|
PushCondition::EventMatch { key, pattern } => { |
|
let mut json = |
|
serde_json::to_value(pdu).expect("PDU is valid JSON"); |
|
for key in key.split('.') { |
|
json = json[key].clone(); |
|
} |
|
// TODO: this is baddddd |
|
json.to_string().contains(pattern) |
|
} |
|
_ => false, |
|
}) {} |
|
} |
|
} |
|
} |
|
".m.rule.contains_display_name" => { |
|
if let EventType::RoomMessage = &pdu.kind { |
|
let msg_content = |
|
serde_json::from_value::<MessageEventContent>(pdu.content.clone()) |
|
.map_err(|_| { |
|
Error::bad_database("PDU contained bad message content") |
|
})?; |
|
if let MessageEventContent::Text(TextMessageEventContent { body, .. }) = |
|
&msg_content |
|
{ |
|
if body.contains(user.localpart()) { |
|
send_notice(user, &pusher, &pdu).await?; |
|
} |
|
} |
|
} |
|
} |
|
".m.rule.tombstone" => {} |
|
".m.rule.roomnotif" => {} |
|
".m.rule.contains_user_name" => { |
|
if let EventType::RoomMessage = &pdu.kind { |
|
let msg_content = |
|
serde_json::from_value::<MessageEventContent>(pdu.content.clone()) |
|
.map_err(|_| { |
|
Error::bad_database("PDU contained bad message content") |
|
})?; |
|
if let MessageEventContent::Text(TextMessageEventContent { body, .. }) = |
|
&msg_content |
|
{ |
|
if body.contains(user.localpart()) { |
|
send_notice(user, &pusher, &pdu).await?; |
|
} |
|
} |
|
} |
|
} |
|
".m.rule.call" => {} |
|
".m.rule.encrypted_room_one_to_one" => {} |
|
".m.rule.room_one_to_one" => {} |
|
".m.rule.message" => {} |
|
".m.rule.encrypted" => {} |
|
_ => {} |
|
} |
|
} |
|
Ok(()) |
|
} |
|
|
|
async fn send_notice(_sender: &UserId, pusher: &Pusher, _event: &PduEvent) -> Result<()> { |
|
if let Some(PusherKind::Http) = pusher.kind { |
|
log::error!("YAHOOO"); |
|
} else { |
|
// EMAIL |
|
todo!("send an email") |
|
} |
|
Ok(()) |
|
}
|
|
|