palpo_data/user/
pusher.rs

1use std::fmt::Debug;
2
3use diesel::prelude::*;
4use palpo_core::push::PusherIds;
5use url::Url;
6
7use crate::core::client::push::pusher::PusherAction;
8use crate::core::client::push::PusherPostData;
9use crate::core::events::room::power_levels::RoomPowerLevelsEventContent;
10use crate::core::events::{AnySyncTimelineEvent, StateEventType, TimelineEventType};
11use crate::core::identifiers::*;
12use crate::core::push::push_gateway::{
13    Device, Notification, NotificationCounts, NotificationPriority, SendEventNotificationReqBody,
14};
15use crate::core::push::{
16    Action, PushConditionPowerLevelsCtx, PushConditionRoomCtx, PushFormat, Pusher, PusherKind, Ruleset, Tweak,
17};
18use crate::core::serde::{JsonValue, RawJson};
19use crate::core::UnixMillis;
20use crate::schema::*;
21use crate::{connect, DataError, DataResult};
22
23#[derive(Identifiable, Queryable, Debug, Clone)]
24#[diesel(table_name = pushers)]
25pub struct DbPusher {
26    pub id: i64,
27
28    pub user_id: OwnedUserId,
29    pub kind: String,
30    pub app_id: String,
31    pub app_display_name: String,
32    pub device_id: OwnedDeviceId,
33    pub device_display_name: String,
34    pub access_token_id: Option<i64>,
35    pub profile_tag: Option<String>,
36    pub pushkey: String,
37    pub lang: String,
38    pub data: JsonValue,
39    pub enabled: bool,
40    pub last_stream_ordering: Option<i64>,
41    pub last_success: Option<i64>,
42    pub failing_since: Option<i64>,
43    pub created_at: UnixMillis,
44}
45#[derive(Insertable, Debug, Clone)]
46#[diesel(table_name = pushers)]
47pub struct NewDbPusher {
48    pub user_id: OwnedUserId,
49    pub kind: String,
50    pub app_id: String,
51    pub app_display_name: String,
52    pub device_id: OwnedDeviceId,
53    pub device_display_name: String,
54    pub access_token_id: Option<i64>,
55    pub profile_tag: Option<String>,
56    pub pushkey: String,
57    pub lang: String,
58    pub data: JsonValue,
59    pub enabled: bool,
60    pub created_at: UnixMillis,
61}
62impl TryInto<Pusher> for DbPusher {
63    type Error = DataError;
64    fn try_into(self) -> DataResult<Pusher> {
65        let Self {
66            user_id,
67            profile_tag,
68            kind,
69            app_id,
70            app_display_name,
71            device_display_name,
72            pushkey,
73            lang,
74            data,
75            ..
76        } = self;
77        Ok(Pusher {
78            ids: PusherIds { app_id, pushkey },
79            profile_tag,
80            kind: PusherKind::try_new(&kind, data)?,
81            app_display_name,
82            device_display_name,
83            lang,
84        })
85    }
86}
87
88pub fn get_pusher(user_id: &UserId, pushkey: &str) -> DataResult<Option<Pusher>> {
89    let pusher = pushers::table
90        .filter(pushers::user_id.eq(user_id))
91        .filter(pushers::pushkey.eq(pushkey))
92        .order_by(pushers::id.desc())
93        .first::<DbPusher>(&mut *connect()?)
94        .optional()?;
95    if let Some(pusher) = pusher {
96        pusher.try_into().map(Option::Some)
97    } else {
98        Ok(None)
99    }
100}
101
102pub fn get_pushers(user_id: &UserId) -> DataResult<Vec<DbPusher>> {
103    pushers::table
104        .filter(pushers::user_id.eq(user_id))
105        .order_by(pushers::id.desc())
106        .load::<DbPusher>(&mut *connect()?)
107        .map_err(Into::into)
108}
109
110pub fn get_actions<'a>(
111    user: &UserId,
112    ruleset: &'a Ruleset,
113    power_levels: &RoomPowerLevelsEventContent,
114    pdu: &RawJson<AnySyncTimelineEvent>,
115    room_id: &RoomId,
116) -> DataResult<&'a [Action]> {
117    let power_levels = PushConditionPowerLevelsCtx {
118        users: power_levels.users.clone(),
119        users_default: power_levels.users_default,
120        notifications: power_levels.notifications.clone(),
121    };
122    let ctx = PushConditionRoomCtx {
123        room_id: room_id.to_owned(),
124        member_count: 10_u32.into(), // TODO: get member count efficiently
125        user_id: user.to_owned(),
126        user_display_name: crate::user::display_name(user)
127            .ok()
128            .flatten()
129            .unwrap_or_else(|| user.localpart().to_owned()),
130        power_levels: Some(power_levels),
131        supported_features: vec![],
132    };
133
134    Ok(ruleset.get_actions(pdu, &ctx))
135}
136
137pub fn get_push_keys(user_id: &UserId) -> DataResult<Vec<String>> {
138    pushers::table
139        .filter(pushers::user_id.eq(user_id))
140        .select(pushers::pushkey)
141        .load::<String>(&mut *connect()?)
142        .map_err(Into::into)
143}