palpo_core/push/push_gateway.rs
1//! `GET /_matrix/client/*/notifications`
2//!
3//! Paginate through the list of events that the user has been, or would have been notified about.
4//! `/v3/` ([spec])
5//!
6//! [spec]: https://spec.matrix.org/latest/client-server-api/#get_matrixclientv3notifications
7use salvo::prelude::*;
8use serde::{Deserialize, Serialize};
9
10use crate::events::TimelineEventType;
11use crate::identifiers::*;
12use crate::push::{PusherData, Tweak};
13use crate::serde::StringEnum;
14use crate::{PrivOwnedStr, RawJsonValue, UnixSeconds};
15
16// const METADATA: Metadata = metadata! {
17// method: POST,
18// rate_limited: false,
19// authentication: None,
20// history: {
21// 1.0 => "/_matrix/push/v1/notify",
22// }
23// };
24
25#[derive(ToSchema, Serialize, Debug)]
26pub struct SendEventNotificationReqBody {
27 /// Information about the push notification
28 pub notification: Notification,
29}
30crate::json_body_modifier!(SendEventNotificationReqBody);
31impl SendEventNotificationReqBody {
32 pub fn new(notification: Notification) -> Self {
33 Self { notification }
34 }
35}
36
37/// Response type for the `send_event_notification` endpoint.
38#[derive(ToSchema, Serialize, Debug)]
39pub struct SendEventNotificationResBody {
40 /// A list of all pushkeys given in the notification request that are not valid.
41 ///
42 /// These could have been rejected by an upstream gateway because they have expired or have
43 /// never been valid. Homeservers must cease sending notification requests for these
44 /// pushkeys and remove the associated pushers. It may not necessarily be the notification
45 /// in the request that failed: it could be that a previous notification to the same
46 /// pushkey failed. May be empty.
47 pub rejected: Vec<String>,
48}
49impl SendEventNotificationResBody {
50 /// Creates a new `Response` with the given list of rejected pushkeys.
51 pub fn new(rejected: Vec<String>) -> Self {
52 Self { rejected }
53 }
54}
55
56/// Represents a notification.
57#[derive(ToSchema, Default, Deserialize, Serialize, Clone, Debug)]
58pub struct Notification {
59 /// The Matrix event ID of the event being notified about.
60 ///
61 /// Required if the notification is about a particular Matrix event. May be omitted for
62 /// notifications that only contain updated badge counts. This ID can and should be used to
63 /// detect duplicate notification requests.
64 #[serde(skip_serializing_if = "Option::is_none")]
65 pub event_id: Option<OwnedEventId>,
66
67 /// The ID of the room in which this event occurred.
68 ///
69 /// Required if the notification relates to a specific Matrix event.
70 #[serde(skip_serializing_if = "Option::is_none")]
71 pub room_id: Option<OwnedRoomId>,
72
73 /// The type of the event as in the event's `type` field.
74 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
75 pub event_type: Option<TimelineEventType>,
76
77 /// The sender of the event as in the corresponding event field.
78 #[serde(skip_serializing_if = "Option::is_none")]
79 pub sender: Option<OwnedUserId>,
80
81 /// The current display name of the sender in the room in which the event occurred.
82 #[serde(skip_serializing_if = "Option::is_none")]
83 pub sender_display_name: Option<String>,
84
85 /// The name of the room in which the event occurred.
86 #[serde(skip_serializing_if = "Option::is_none")]
87 pub room_name: Option<String>,
88
89 /// An alias to display for the room in which the event occurred.
90 #[serde(skip_serializing_if = "Option::is_none")]
91 pub room_alias: Option<OwnedRoomAliasId>,
92
93 /// Whether the user receiving the notification is the subject of a member event (i.e. the
94 /// `state_key` of the member event is equal to the user's Matrix ID).
95 #[serde(default, skip_serializing_if = "crate::serde::is_default")]
96 pub user_is_target: bool,
97
98 /// The priority of the notification.
99 ///
100 /// If omitted, `high` is assumed. This may be used by push gateways to deliver less
101 /// time-sensitive notifications in a way that will preserve battery power on mobile
102 /// devices.
103 #[serde(default, skip_serializing_if = "crate::serde::is_default")]
104 pub prio: NotificationPriority,
105
106 /// The `content` field from the event, if present.
107 ///
108 /// The pusher may omit this if the event had no content or for any other reason.
109 #[serde(skip_serializing_if = "Option::is_none")]
110 #[salvo(schema(value_type = Object))]
111 pub content: Option<Box<RawJsonValue>>,
112
113 /// Current number of unacknowledged communications for the recipient user.
114 ///
115 /// Counts whose value is zero should be omitted.
116 #[serde(default, skip_serializing_if = "NotificationCounts::is_default")]
117 pub counts: NotificationCounts,
118
119 /// An array of devices that the notification should be sent to.
120 pub devices: Vec<Device>,
121}
122impl Notification {
123 /// Create a new notification for the given devices.
124 pub fn new(devices: Vec<Device>) -> Self {
125 Notification {
126 devices,
127 ..Default::default()
128 }
129 }
130}
131
132/// Type for passing information about notification priority.
133///
134/// This may be used by push gateways to deliver less time-sensitive
135/// notifications in a way that will preserve battery power on mobile devices.
136///
137/// This type can hold an arbitrary string. To build this with a custom value, convert it from a
138/// string with `::from()` / `.into()`. To check for values that are not available as a
139/// documented variant here, use its string representation, obtained through `.as_str()`.
140#[derive(ToSchema, Clone, Default, PartialEq, Eq, StringEnum)]
141#[palpo_enum(rename_all = "snake_case")]
142#[non_exhaustive]
143pub enum NotificationPriority {
144 /// A high priority notification
145 #[default]
146 High,
147
148 /// A low priority notification
149 Low,
150
151 #[doc(hidden)]
152 #[salvo(schema(skip))]
153 _Custom(PrivOwnedStr),
154}
155
156/// Type for passing information about notification counts.
157#[derive(ToSchema, Deserialize, Serialize, Default, Clone, Debug)]
158pub struct NotificationCounts {
159 /// The number of unread messages a user has across all of the rooms they
160 /// are a member of.
161 #[serde(default, skip_serializing_if = "crate::serde::is_default")]
162 pub unread: usize,
163
164 /// The number of unacknowledged missed calls a user has across all rooms of
165 /// which they are a member.
166 #[serde(default, skip_serializing_if = "crate::serde::is_default")]
167 pub missed_calls: usize,
168}
169
170impl NotificationCounts {
171 /// Create new notification counts from the given unread and missed call
172 /// counts.
173 pub fn new(unread: usize, missed_calls: usize) -> Self {
174 NotificationCounts { unread, missed_calls }
175 }
176
177 fn is_default(&self) -> bool {
178 self.unread == 0 && self.missed_calls == 0
179 }
180}
181
182/// Type for passing information about devices.
183#[derive(ToSchema, Clone, Debug, Deserialize, Serialize)]
184pub struct Device {
185 /// The `app_id` given when the pusher was created.
186 ///
187 /// Max length: 64 chars.
188 pub app_id: String,
189
190 /// The `pushkey` given when the pusher was created.
191 ///
192 /// Max length: 512 bytes.
193 pub pushkey: String,
194
195 /// The unix timestamp (in seconds) when the pushkey was last updated.
196 #[serde(skip_serializing_if = "Option::is_none")]
197 pub pushkey_ts: Option<UnixSeconds>,
198
199 /// A dictionary of additional pusher-specific data.
200 #[serde(default, skip_serializing_if = "PusherData::is_empty")]
201 pub data: PusherData,
202
203 /// A dictionary of customisations made to the way this notification is to be presented.
204 ///
205 /// These are added by push rules.
206 #[serde(skip_serializing_if = "Vec::is_empty")]
207 pub tweaks: Vec<Tweak>,
208}
209
210impl Device {
211 /// Create a new device with the given app id and pushkey
212 pub fn new(app_id: String, pushkey: String) -> Self {
213 Device {
214 app_id,
215 pushkey,
216 pushkey_ts: None,
217 data: PusherData::new(),
218 tweaks: Vec::new(),
219 }
220 }
221}