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(), 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}