WIP: send out push notification, impl pusher routes
It seems in order to test this I may also have to impl the email 3pid route? I need to call the set_pusher route somehow.
This commit is contained in:
parent
a0ecd76e21
commit
2d69e81699
6 changed files with 514 additions and 166 deletions
148
src/database/pusher.rs
Normal file
148
src/database/pusher.rs
Normal file
|
@ -0,0 +1,148 @@
|
|||
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(())
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue