Implement notifications retrieval. (closes #201)
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
@@ -3,18 +3,41 @@ use std::{collections::HashSet, sync::Arc};
|
||||
use futures::StreamExt;
|
||||
use ruma::{
|
||||
OwnedUserId, RoomId, UserId,
|
||||
api::client::push::ProfileTag,
|
||||
events::{GlobalAccountDataEventType, TimelineEventType, push_rules::PushRulesEvent},
|
||||
push::{Action, Ruleset, Tweak},
|
||||
push::{Action, Actions, Ruleset, Tweak},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tuwunel_core::{
|
||||
Result, implement,
|
||||
matrix::{
|
||||
event::Event,
|
||||
pdu::{Pdu, RawPduId},
|
||||
pdu::{Count, Pdu, PduId, RawPduId},
|
||||
},
|
||||
utils::{self, ReadyExt},
|
||||
utils::{self, ReadyExt, time::now_millis},
|
||||
};
|
||||
use tuwunel_database::Map;
|
||||
use tuwunel_database::{Json, Map};
|
||||
|
||||
use crate::rooms::short::ShortRoomId;
|
||||
|
||||
/// Succinct version of Ruma's Notification. Appended to the database when the
|
||||
/// user is notified. The PduCount is part of the database key so only the
|
||||
/// shortroomid is included. Together they make the PduId.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Notified {
|
||||
/// Milliseconds time at which the event notification was sent.
|
||||
pub ts: u64,
|
||||
|
||||
/// ShortRoomId
|
||||
pub sroomid: ShortRoomId,
|
||||
|
||||
/// The profile tag of the rule that matched this event.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tag: Option<ProfileTag>,
|
||||
|
||||
/// Actions vector
|
||||
pub actions: Actions,
|
||||
}
|
||||
|
||||
/// Called by timeline append_pdu.
|
||||
#[implement(super::Service)]
|
||||
@@ -77,12 +100,13 @@ pub(crate) async fn append_pdu(&self, pdu_id: RawPduId, pdu: &Pdu) -> Result {
|
||||
.get_power_levels(pdu.room_id())
|
||||
.await?;
|
||||
|
||||
for action in self
|
||||
let actions = self
|
||||
.services
|
||||
.pusher
|
||||
.get_actions(user, &rules_for_user, &power_levels, &serialized, pdu.room_id())
|
||||
.await
|
||||
{
|
||||
.await;
|
||||
|
||||
for action in actions {
|
||||
match action {
|
||||
| Action::Notify => notify = true,
|
||||
| Action::SetTweak(Tweak::Highlight(true)) => {
|
||||
@@ -109,6 +133,20 @@ pub(crate) async fn append_pdu(&self, pdu_id: RawPduId, pdu: &Pdu) -> Result {
|
||||
continue;
|
||||
}
|
||||
|
||||
let id: PduId = pdu_id.into();
|
||||
let notified = Notified {
|
||||
ts: now_millis(),
|
||||
sroomid: id.shortroomid,
|
||||
tag: None,
|
||||
actions: actions.into(),
|
||||
};
|
||||
|
||||
if matches!(id.count, Count::Normal(_)) {
|
||||
self.db
|
||||
.useridcount_notification
|
||||
.put((user, id.count.into_unsigned()), Json(notified));
|
||||
}
|
||||
|
||||
self.services
|
||||
.pusher
|
||||
.get_pushkeys(user)
|
||||
|
||||
@@ -17,10 +17,12 @@ use ruma::{
|
||||
};
|
||||
use tuwunel_core::{
|
||||
Err, Result, err, implement,
|
||||
utils::stream::{BroadbandExt, TryIgnore},
|
||||
utils::stream::{BroadbandExt, ReadyExt, TryIgnore},
|
||||
};
|
||||
use tuwunel_database::{Database, Deserialized, Ignore, Interfix, Json, Map};
|
||||
|
||||
pub use self::append::Notified;
|
||||
|
||||
pub struct Service {
|
||||
db: Data,
|
||||
services: Arc<crate::services::OnceServices>,
|
||||
@@ -29,6 +31,7 @@ pub struct Service {
|
||||
struct Data {
|
||||
senderkey_pusher: Arc<Map>,
|
||||
pushkey_deviceid: Arc<Map>,
|
||||
useridcount_notification: Arc<Map>,
|
||||
userroomid_highlightcount: Arc<Map>,
|
||||
userroomid_notificationcount: Arc<Map>,
|
||||
roomuserid_lastnotificationread: Arc<Map>,
|
||||
@@ -41,6 +44,7 @@ impl crate::Service for Service {
|
||||
db: Data {
|
||||
senderkey_pusher: args.db["senderkey_pusher"].clone(),
|
||||
pushkey_deviceid: args.db["pushkey_deviceid"].clone(),
|
||||
useridcount_notification: args.db["useridcount_notification"].clone(),
|
||||
userroomid_highlightcount: args.db["userroomid_highlightcount"].clone(),
|
||||
userroomid_notificationcount: args.db["userroomid_notificationcount"].clone(),
|
||||
roomuserid_lastnotificationread: args.db["roomuserid_lastnotificationread"]
|
||||
@@ -193,6 +197,27 @@ pub fn get_pushkeys<'a>(&'a self, sender: &'a UserId) -> impl Stream<Item = &str
|
||||
.map(|(_, pushkey): (Ignore, &str)| pushkey)
|
||||
}
|
||||
|
||||
#[implement(Service)]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
#[inline]
|
||||
pub fn get_notifications<'a>(
|
||||
&'a self,
|
||||
sender: &'a UserId,
|
||||
from: Option<u64>,
|
||||
) -> impl Stream<Item = (u64, Notified)> + Send + 'a {
|
||||
let from = from
|
||||
.map(|from| from.saturating_sub(1))
|
||||
.unwrap_or(u64::MAX);
|
||||
|
||||
self.db
|
||||
.useridcount_notification
|
||||
.rev_stream_from(&(sender, from))
|
||||
.ignore_err()
|
||||
.map(|item: ((&UserId, u64), _)| (item.0, item.1))
|
||||
.ready_take_while(move |((user_id, _count), _)| sender == *user_id)
|
||||
.map(|((_, count), notified)| (count, notified))
|
||||
}
|
||||
|
||||
#[implement(Service)]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
pub async fn get_actions<'a>(
|
||||
|
||||
Reference in New Issue
Block a user