diff --git a/crates/matrix-sdk/src/live_location_share.rs b/crates/matrix-sdk/src/live_location_share.rs index f2d3e4fa097..5a407e3b2dc 100644 --- a/crates/matrix-sdk/src/live_location_share.rs +++ b/crates/matrix-sdk/src/live_location_share.rs @@ -43,20 +43,23 @@ impl ObservableLiveLocation { /// Get a stream of [`LiveLocationShare`]. pub fn subscribe(&self) -> impl Stream { let stream = self.observable_room_events.subscribe(); + stream! { for await (event, room) in stream { - yield LiveLocationShare { - last_location: LastLocation { - location: event.content.location, - ts: event.origin_server_ts, - }, - beacon_info: room - .get_user_beacon_info(&event.sender) - .await - .ok() - .map(|info| info.content), - user_id: event.sender, - }; + if event.sender != room.own_user_id() { + yield LiveLocationShare { + last_location: LastLocation { + location: event.content.location, + ts: event.origin_server_ts, + }, + beacon_info: room + .get_user_beacon_info(&event.sender) + .await + .ok() + .map(|info| info.content), + user_id: event.sender, + }; + } } } } diff --git a/crates/matrix-sdk/src/room/mod.rs b/crates/matrix-sdk/src/room/mod.rs index 19210294482..521f569925e 100644 --- a/crates/matrix-sdk/src/room/mod.rs +++ b/crates/matrix-sdk/src/room/mod.rs @@ -3244,6 +3244,9 @@ impl Room { /// /// The returned observable will receive the newest event for each sync /// response that contains an `m.beacon` event. + /// + /// Returns a stream of [`ObservableLiveLocation`] events from other users + /// in the room, excluding the live location events of the room's own user. pub fn observe_live_location_shares(&self) -> ObservableLiveLocation { ObservableLiveLocation::new(&self.client, self.room_id()) } diff --git a/crates/matrix-sdk/tests/integration/room/beacon/mod.rs b/crates/matrix-sdk/tests/integration/room/beacon/mod.rs index 2f3403087a4..50b60f0de20 100644 --- a/crates/matrix-sdk/tests/integration/room/beacon/mod.rs +++ b/crates/matrix-sdk/tests/integration/room/beacon/mod.rs @@ -1,13 +1,24 @@ use std::time::{Duration, UNIX_EPOCH}; -use futures_util::{pin_mut, StreamExt as _}; +use futures_util::{pin_mut, FutureExt, StreamExt as _}; use js_int::uint; -use matrix_sdk::{config::SyncSettings, live_location_share::LiveLocationShare}; +use matrix_sdk::{ + config::SyncSettings, live_location_share::LiveLocationShare, + test_utils::mocks::MatrixMockServer, +}; use matrix_sdk_test::{ - async_test, mocks::mock_encryption_state, sync_timeline_event, test_json, JoinedRoomBuilder, - SyncResponseBuilder, DEFAULT_TEST_ROOM_ID, + async_test, event_factory::EventFactory, mocks::mock_encryption_state, sync_timeline_event, + test_json, JoinedRoomBuilder, SyncResponseBuilder, DEFAULT_TEST_ROOM_ID, +}; +use ruma::{ + event_id, + events::{ + beacon::BeaconEventContent, beacon_info::BeaconInfoEventContent, location::AssetType, + }, + owned_event_id, room_id, + time::SystemTime, + user_id, MilliSecondsSinceUnixEpoch, }; -use ruma::{event_id, events::location::AssetType, time::SystemTime, MilliSecondsSinceUnixEpoch}; use serde_json::json; use wiremock::{ matchers::{body_partial_json, header, method, path_regex}, @@ -130,8 +141,8 @@ async fn test_send_location_beacon_with_expired_live_share() { }, "event_id": "$15139375514XsgmR:localhost", "origin_server_ts": 1_636_829_458, - "sender": "@example:localhost", - "state_key": "@example:localhost", + "sender": "@example2:localhost", + "state_key": "@example2:localhost", "type": "org.matrix.msc3672.beacon_info", "unsigned": { "age": 7034220 @@ -192,8 +203,8 @@ async fn test_most_recent_event_in_stream() { }, "event_id": "$15139375514XsgmR:localhost", "origin_server_ts": millis_time, - "sender": "@example:localhost", - "state_key": "@example:localhost", + "sender": "@example2:localhost", + "state_key": "@example2:localhost", "type": "org.matrix.msc3672.beacon_info", "unsigned": { "age": 7034220 @@ -235,7 +246,7 @@ async fn test_most_recent_event_in_stream() { }, "event_id": format!("$event_for_stream_{nth}"), "origin_server_ts": 1_636_829_458, - "sender": "@example:localhost", + "sender": "@example2:localhost", "type": "org.matrix.msc3672.beacon", "unsigned": { "age": 598971 @@ -256,7 +267,7 @@ async fn test_most_recent_event_in_stream() { let LiveLocationShare { user_id, last_location, beacon_info } = stream.next().await.expect("Another live location was expected"); - assert_eq!(user_id.to_string(), "@example:localhost"); + assert_eq!(user_id.to_string(), "@example2:localhost"); assert_eq!(last_location.location.uri, "geo:24.9575274619722,12.494122581370175;u=24"); @@ -305,8 +316,8 @@ async fn test_observe_single_live_location_share() { }, "event_id": "$test_beacon_info", "origin_server_ts": millis_time, - "sender": "@example:localhost", - "state_key": "@example:localhost", + "sender": "@example2:localhost", + "state_key": "@example2:localhost", "type": "org.matrix.msc3672.beacon_info", } ] @@ -341,7 +352,7 @@ async fn test_observe_single_live_location_share() { }, "event_id": "$location_event", "origin_server_ts": millis_time, - "sender": "@example:localhost", + "sender": "@example2:localhost", "type": "org.matrix.msc3672.beacon", }); @@ -362,7 +373,7 @@ async fn test_observe_single_live_location_share() { let LiveLocationShare { user_id, last_location, beacon_info } = stream.next().await.expect("Another live location was expected"); - assert_eq!(user_id.to_string(), "@example:localhost"); + assert_eq!(user_id.to_string(), "@example2:localhost"); assert_eq!(last_location.location.uri, "geo:10.000000,20.000000;u=5"); assert_eq!(last_location.ts, current_time); @@ -374,3 +385,44 @@ async fn test_observe_single_live_location_share() { assert_eq!(beacon_info.timeout, Duration::from_millis(3000)); assert_eq!(beacon_info.ts, current_time); } + +#[async_test] +async fn test_observing_live_location_does_not_return_own_beacon_updates() { + let server = MatrixMockServer::new().await; + let client = server.client_builder().build().await; + let room_id = room_id!("!a:b.c"); + let event_id = event_id!("$a:b.c"); + let user_id = user_id!("@example:localhost"); + + let f = EventFactory::new().room(room_id); + + let joined_room_builder = JoinedRoomBuilder::new(room_id).add_state_bulk(vec![f + .event(BeaconInfoEventContent::new(None, Duration::from_secs(60), false, None)) + .event_id(event_id) + .sender(user_id) + .state_key(user_id) + .into_raw_timeline() + .cast()]); + + let room = server.sync_room(&client, joined_room_builder).await; + + let observable_live_location_shares = room.observe_live_location_shares(); + let stream = observable_live_location_shares.subscribe(); + pin_mut!(stream); + + let beacon_event = f + .event(BeaconEventContent::new( + owned_event_id!("$15139375514XsgmR:localhost"), + "geo:51.5008,0.1247;u=35".to_owned(), + Some(MilliSecondsSinceUnixEpoch(uint!(1_636_829_458))), + )) + .event_id(event_id!("$152037dfsef280074GZeOm:localhost")) + .sender(user_id) + .into_raw_sync(); + + let joined = JoinedRoomBuilder::new(room_id).add_timeline_event(beacon_event); + + let _ = server.sync_room(&client, joined).await; + + assert!(stream.next().now_or_never().is_none()); +}