17
17
18
18
use std:: collections:: BTreeMap ;
19
19
20
- use matrix_sdk_base:: deserialized_responses:: RawAnySyncOrStrippedState ;
20
+ use matrix_sdk_base:: deserialized_responses:: { EncryptionInfo , RawAnySyncOrStrippedState } ;
21
21
use ruma:: {
22
22
api:: client:: {
23
23
account:: request_openid_token:: v3:: { Request as OpenIdRequest , Response as OpenIdResponse } ,
24
24
delayed_events:: { self , update_delayed_event:: unstable:: UpdateAction } ,
25
25
filter:: RoomEventFilter ,
26
+ to_device:: send_event_to_device:: { self , v3:: Request as RumaToDeviceRequest } ,
26
27
} ,
27
28
assign,
28
29
events:: {
29
30
AnyMessageLikeEventContent , AnyStateEventContent , AnySyncMessageLikeEvent ,
30
- AnySyncStateEvent , AnySyncTimelineEvent , AnyTimelineEvent , MessageLikeEventType ,
31
- StateEventType , TimelineEventType ,
31
+ AnySyncStateEvent , AnySyncTimelineEvent , AnyTimelineEvent , AnyToDeviceEvent ,
32
+ AnyToDeviceEventContent , MessageLikeEventType , StateEventType , TimelineEventType ,
33
+ ToDeviceEventType ,
32
34
} ,
33
35
serde:: { from_raw_json_value, Raw } ,
34
- EventId , RoomId , TransactionId ,
36
+ to_device:: DeviceIdOrAllDevices ,
37
+ EventId , OwnedUserId , RoomId , TransactionId ,
35
38
} ;
36
39
use serde_json:: { value:: RawValue as RawJsonValue , Value } ;
37
40
use tokio:: sync:: mpsc:: { unbounded_channel, UnboundedReceiver } ;
@@ -86,7 +89,11 @@ impl MatrixDriver {
86
89
) -> Result < Vec < Raw < AnyTimelineEvent > > > {
87
90
let room_id = self . room . room_id ( ) ;
88
91
let convert = |sync_or_stripped_state| match sync_or_stripped_state {
89
- RawAnySyncOrStrippedState :: Sync ( ev) => Some ( attach_room_id ( ev. cast_ref ( ) , room_id) ) ,
92
+ RawAnySyncOrStrippedState :: Sync ( ev) => with_attached_room_id ( ev. cast_ref ( ) , room_id)
93
+ . map_err ( |e| {
94
+ error ! ( "failed to convert event from `get_state_event` response:{}" , e)
95
+ } )
96
+ . ok ( ) ,
90
97
RawAnySyncOrStrippedState :: Stripped ( _) => {
91
98
error ! ( "MatrixDriver can't operate in invited rooms" ) ;
92
99
None
@@ -181,7 +188,7 @@ impl MatrixDriver {
181
188
182
189
/// Starts forwarding new room events. Once the returned `EventReceiver`
183
190
/// is dropped, forwarding will be stopped.
184
- pub ( crate ) fn events ( & self ) -> EventReceiver {
191
+ pub ( crate ) fn events ( & self ) -> EventReceiver < Raw < AnyTimelineEvent > > {
185
192
let ( tx, rx) = unbounded_channel ( ) ;
186
193
let room_id = self . room . room_id ( ) . to_owned ( ) ;
187
194
@@ -190,14 +197,29 @@ impl MatrixDriver {
190
197
let _room_id = room_id. clone ( ) ;
191
198
let handle_msg_like =
192
199
self . room . add_event_handler ( move |raw : Raw < AnySyncMessageLikeEvent > | {
193
- let _ = _tx. send ( attach_room_id ( raw. cast_ref ( ) , & _room_id) ) ;
200
+ match with_attached_room_id ( raw. cast_ref ( ) , & _room_id) {
201
+ Ok ( event_with_room_id) => {
202
+ let _ = _tx. send ( event_with_room_id) ;
203
+ }
204
+ Err ( e) => {
205
+ error ! ( "Failed to attach room id to message like event: {}" , e) ;
206
+ }
207
+ }
194
208
async { }
195
209
} ) ;
196
210
let drop_guard_msg_like = self . room . client ( ) . event_handler_drop_guard ( handle_msg_like) ;
197
-
211
+ let _room_id = room_id;
212
+ let _tx = tx;
198
213
// Get only all state events from the state section of the sync.
199
214
let handle_state = self . room . add_event_handler ( move |raw : Raw < AnySyncStateEvent > | {
200
- let _ = tx. send ( attach_room_id ( raw. cast_ref ( ) , & room_id) ) ;
215
+ match with_attached_room_id ( raw. cast_ref ( ) , & _room_id) {
216
+ Ok ( event_with_room_id) => {
217
+ let _ = _tx. send ( event_with_room_id) ;
218
+ }
219
+ Err ( e) => {
220
+ error ! ( "Failed to attach room id to state event: {}" , e) ;
221
+ }
222
+ }
201
223
async { }
202
224
} ) ;
203
225
let drop_guard_state = self . room . client ( ) . event_handler_drop_guard ( handle_state) ;
@@ -208,25 +230,102 @@ impl MatrixDriver {
208
230
// section of the sync will not be forwarded to the widget.
209
231
// TODO annotate the events and send both timeline and state section state
210
232
// events.
211
- EventReceiver { rx, _drop_guards : [ drop_guard_msg_like, drop_guard_state] }
233
+ EventReceiver { rx, _drop_guards : vec ! [ drop_guard_msg_like, drop_guard_state] }
234
+ }
235
+
236
+ /// Starts forwarding new room events. Once the returned `EventReceiver`
237
+ /// is dropped, forwarding will be stopped.
238
+ pub ( crate ) fn to_device_events ( & self ) -> EventReceiver < Raw < AnyToDeviceEvent > > {
239
+ let ( tx, rx) = unbounded_channel ( ) ;
240
+
241
+ let to_device_handle = self . room . client ( ) . add_event_handler (
242
+ move |raw : Raw < AnyToDeviceEvent > , encryption_info : Option < EncryptionInfo > | {
243
+ match with_attached_encryption_flag ( raw, & encryption_info) {
244
+ Ok ( ev) => {
245
+ let _ = tx. send ( ev) ;
246
+ }
247
+ Err ( e) => {
248
+ error ! ( "Failed to attach encryption flag to to_device event: {}" , e) ;
249
+ }
250
+ }
251
+ async { }
252
+ } ,
253
+ ) ;
254
+
255
+ let drop_guard = self . room . client ( ) . event_handler_drop_guard ( to_device_handle) ;
256
+ EventReceiver { rx, _drop_guards : vec ! [ drop_guard] }
257
+ }
258
+
259
+ /// It will ignore all devices where errors occurred or where the device is
260
+ /// not verified or where th user has a has_verification_violation.
261
+ pub ( crate ) async fn send_to_device (
262
+ & self ,
263
+ event_type : ToDeviceEventType ,
264
+ encrypted : bool ,
265
+ messages : BTreeMap <
266
+ OwnedUserId ,
267
+ BTreeMap < DeviceIdOrAllDevices , Raw < AnyToDeviceEventContent > > ,
268
+ > ,
269
+ ) -> Result < send_event_to_device:: v3:: Response > {
270
+ let client = self . room . client ( ) ;
271
+
272
+ let request = if encrypted {
273
+ return Err ( Error :: UnknownError (
274
+ "Sending encrypted to_device events is not supported by the widget driver." . into ( ) ,
275
+ ) ) ;
276
+ } else {
277
+ RumaToDeviceRequest :: new_raw ( event_type, TransactionId :: new ( ) , messages)
278
+ } ;
279
+
280
+ let response = client. send ( request) . await ;
281
+
282
+ response. map_err ( Into :: into)
212
283
}
213
284
}
214
285
215
286
/// A simple entity that wraps an `UnboundedReceiver`
216
287
/// along with the drop guard for the room event handler.
217
- pub ( crate ) struct EventReceiver {
218
- rx : UnboundedReceiver < Raw < AnyTimelineEvent > > ,
219
- _drop_guards : [ EventHandlerDropGuard ; 2 ] ,
288
+ pub ( crate ) struct EventReceiver < E > {
289
+ rx : UnboundedReceiver < E > ,
290
+ _drop_guards : Vec < EventHandlerDropGuard > ,
220
291
}
221
292
222
- impl EventReceiver {
223
- pub ( crate ) async fn recv ( & mut self ) -> Option < Raw < AnyTimelineEvent > > {
293
+ impl < T > EventReceiver < T > {
294
+ pub ( crate ) async fn recv ( & mut self ) -> Option < T > {
224
295
self . rx . recv ( ) . await
225
296
}
226
297
}
227
298
228
- fn attach_room_id ( raw_ev : & Raw < AnySyncTimelineEvent > , room_id : & RoomId ) -> Raw < AnyTimelineEvent > {
229
- let mut ev_obj = raw_ev. deserialize_as :: < BTreeMap < String , Box < RawJsonValue > > > ( ) . unwrap ( ) ;
230
- ev_obj. insert ( "room_id" . to_owned ( ) , serde_json:: value:: to_raw_value ( room_id) . unwrap ( ) ) ;
231
- Raw :: new ( & ev_obj) . unwrap ( ) . cast ( )
299
+ /// Attach a room id to the event. This is needed because the widget API
300
+ /// requires the room id to be present in the event.
301
+
302
+ fn with_attached_room_id (
303
+ raw : & Raw < AnySyncTimelineEvent > ,
304
+ room_id : & RoomId ,
305
+ ) -> Result < Raw < AnyTimelineEvent > > {
306
+ // This is the only modification we need to do to the events otherwise they are
307
+ // just forwarded raw to the widget.
308
+ // This is why we do the serialization dance here to allow the optimization of
309
+ // using `BTreeMap<String, Box<RawJsonValue>` instead of serializing the full event.
310
+ match raw. deserialize_as :: < BTreeMap < String , Box < RawJsonValue > > > ( ) {
311
+ Ok ( mut ev_mut) => {
312
+ ev_mut. insert ( "room_id" . to_owned ( ) , serde_json:: value:: to_raw_value ( room_id) ?) ;
313
+ Ok ( Raw :: new ( & ev_mut) ?. cast ( ) )
314
+ }
315
+ Err ( e) => Err ( Error :: from ( e) ) ,
316
+ }
317
+ }
318
+
319
+ fn with_attached_encryption_flag (
320
+ raw : Raw < AnyToDeviceEvent > ,
321
+ encryption_info : & Option < EncryptionInfo > ,
322
+ ) -> Result < Raw < AnyToDeviceEvent > > {
323
+ match raw. deserialize_as :: < BTreeMap < String , Box < RawJsonValue > > > ( ) {
324
+ Ok ( mut ev_mut) => {
325
+ let encrypted = encryption_info. is_some ( ) ;
326
+ ev_mut. insert ( "encrypted" . to_owned ( ) , serde_json:: value:: to_raw_value ( & encrypted) ?) ;
327
+ Ok ( Raw :: new ( & ev_mut) ?. cast ( ) )
328
+ }
329
+ Err ( e) => Err ( Error :: from ( e) ) ,
330
+ }
232
331
}
0 commit comments