Skip to content

Commit 781fdf4

Browse files
author
Kerry
authored
Live location sharing - update beacon_info implementation to latest MSC (#2281)
* remove M_BEACON_INFO_VARIABLE Signed-off-by: Kerry Archibald <[email protected]> * create beacon_info events with non-variable event type Signed-off-by: Kerry Archibald <[email protected]> * remove isBeaconInfoEventType Signed-off-by: Kerry Archibald <[email protected]> * refer to msc3673 instead of msc3489 Signed-off-by: Kerry Archibald <[email protected]> * remove event type suffix Signed-off-by: Kerry Archibald <[email protected]> * update beacon identifier to use state key Signed-off-by: Kerry Archibald <[email protected]> * fix beacon spec Signed-off-by: Kerry Archibald <[email protected]> * fix room-state tests Signed-off-by: Kerry Archibald <[email protected]> * add beacon identifier Signed-off-by: Kerry Archibald <[email protected]> * dont allow update to older beacon event Signed-off-by: Kerry Archibald <[email protected]> * lint Signed-off-by: Kerry Archibald <[email protected]> * unnest beacon_info content Signed-off-by: Kerry Archibald <[email protected]> * lint Signed-off-by: Kerry Archibald <[email protected]> * check redaction event id Signed-off-by: Kerry Archibald <[email protected]>
1 parent dde4285 commit 781fdf4

File tree

10 files changed

+108
-117
lines changed

10 files changed

+108
-117
lines changed

spec/test-utils/beacon.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ export const makeBeaconInfoEvent = (
4242
roomId: string,
4343
contentProps: Partial<InfoContentProps> = {},
4444
eventId?: string,
45-
eventTypeSuffix?: string,
4645
): MatrixEvent => {
4746
const {
4847
timeout, isLive, description, assetType,
@@ -51,12 +50,14 @@ export const makeBeaconInfoEvent = (
5150
...contentProps,
5251
};
5352
const event = new MatrixEvent({
54-
type: `${M_BEACON_INFO.name}.${sender}.${eventTypeSuffix || Date.now()}`,
53+
type: M_BEACON_INFO.name,
5554
room_id: roomId,
5655
state_key: sender,
5756
content: makeBeaconInfoContent(timeout, isLive, description, assetType),
5857
});
5958

59+
event.event.origin_server_ts = Date.now();
60+
6061
// live beacons use the beacon_info event id
6162
// set or default this
6263
event.replaceLocalEventId(eventId || `$${Math.random()}-${Math.random()}`);

spec/unit/content-helpers.spec.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ limitations under the License.
1616

1717
import { REFERENCE_RELATION } from "matrix-events-sdk";
1818

19-
import { M_BEACON_INFO } from "../../src/@types/beacon";
2019
import { LocationAssetType, M_ASSET, M_LOCATION, M_TIMESTAMP } from "../../src/@types/location";
2120
import { makeBeaconContent, makeBeaconInfoContent } from "../../src/content-helpers";
2221

@@ -36,11 +35,9 @@ describe('Beacon content helpers', () => {
3635
'nice beacon_info',
3736
LocationAssetType.Pin,
3837
)).toEqual({
39-
[M_BEACON_INFO.name]: {
40-
description: 'nice beacon_info',
41-
timeout: 1234,
42-
live: true,
43-
},
38+
description: 'nice beacon_info',
39+
timeout: 1234,
40+
live: true,
4441
[M_TIMESTAMP.name]: mockDateNow,
4542
[M_ASSET.name]: {
4643
type: LocationAssetType.Pin,

spec/unit/matrix-client.spec.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -999,10 +999,10 @@ describe("MatrixClient", function() {
999999
});
10001000

10011001
it("creates new beacon info", async () => {
1002-
await client.unstable_createLiveBeacon(roomId, content, '123');
1002+
await client.unstable_createLiveBeacon(roomId, content);
10031003

10041004
// event type combined
1005-
const expectedEventType = `${M_BEACON_INFO.name}.${userId}.123`;
1005+
const expectedEventType = M_BEACON_INFO.name;
10061006
const [callback, method, path, queryParams, requestContent] = client.http.authedRequest.mock.calls[0];
10071007
expect(callback).toBeFalsy();
10081008
expect(method).toBe('PUT');
@@ -1015,15 +1015,13 @@ describe("MatrixClient", function() {
10151015
});
10161016

10171017
it("updates beacon info with specific event type", async () => {
1018-
const eventType = `${M_BEACON_INFO.name}.${userId}.456`;
1019-
1020-
await client.unstable_setLiveBeacon(roomId, eventType, content);
1018+
await client.unstable_setLiveBeacon(roomId, content);
10211019

10221020
// event type combined
10231021
const [, , path, , requestContent] = client.http.authedRequest.mock.calls[0];
10241022
expect(path).toEqual(
10251023
`/rooms/${encodeURIComponent(roomId)}/state/` +
1026-
`${encodeURIComponent(eventType)}/${encodeURIComponent(userId)}`,
1024+
`${encodeURIComponent(M_BEACON_INFO.name)}/${encodeURIComponent(userId)}`,
10271025
);
10281026
expect(requestContent).toEqual(content);
10291027
});

spec/unit/models/beacon.spec.ts

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,8 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
import { EventType } from "../../../src";
18-
import { M_BEACON_INFO } from "../../../src/@types/beacon";
1917
import {
2018
isTimestampInDuration,
21-
isBeaconInfoEventType,
2219
Beacon,
2320
BeaconEvent,
2421
} from "../../../src/models/beacon";
@@ -57,27 +54,9 @@ describe('Beacon', () => {
5754
});
5855
});
5956

60-
describe('isBeaconInfoEventType', () => {
61-
it.each([
62-
EventType.CallAnswer,
63-
`prefix.${M_BEACON_INFO.name}`,
64-
`prefix.${M_BEACON_INFO.altName}`,
65-
])('returns false for %s', (type) => {
66-
expect(isBeaconInfoEventType(type)).toBe(false);
67-
});
68-
69-
it.each([
70-
M_BEACON_INFO.name,
71-
M_BEACON_INFO.altName,
72-
`${M_BEACON_INFO.name}.@test:server.org.12345`,
73-
`${M_BEACON_INFO.altName}.@test:server.org.12345`,
74-
])('returns true for %s', (type) => {
75-
expect(isBeaconInfoEventType(type)).toBe(true);
76-
});
77-
});
78-
7957
describe('Beacon', () => {
8058
const userId = '@user:server.org';
59+
const userId2 = '@user2:server.org';
8160
const roomId = '$room:server.org';
8261
// 14.03.2022 16:15
8362
const now = 1647270879403;
@@ -88,6 +67,7 @@ describe('Beacon', () => {
8867
// without timeout of 3 hours
8968
let liveBeaconEvent;
9069
let notLiveBeaconEvent;
70+
let user2BeaconEvent;
9171

9272
const advanceDateAndTime = (ms: number) => {
9373
// bc liveness check uses Date.now we have to advance this mock
@@ -107,14 +87,21 @@ describe('Beacon', () => {
10787
isLive: true,
10888
},
10989
'$live123',
110-
'$live123',
11190
);
11291
notLiveBeaconEvent = makeBeaconInfoEvent(
11392
userId,
11493
roomId,
11594
{ timeout: HOUR_MS * 3, isLive: false },
11695
'$dead123',
117-
'$dead123',
96+
);
97+
user2BeaconEvent = makeBeaconInfoEvent(
98+
userId2,
99+
roomId,
100+
{
101+
timeout: HOUR_MS * 3,
102+
isLive: true,
103+
},
104+
'$user2live123',
118105
);
119106

120107
// back to now
@@ -133,7 +120,7 @@ describe('Beacon', () => {
133120
expect(beacon.isLive).toEqual(true);
134121
expect(beacon.beaconInfoOwner).toEqual(userId);
135122
expect(beacon.beaconInfoEventType).toEqual(liveBeaconEvent.getType());
136-
expect(beacon.identifier).toEqual(liveBeaconEvent.getType());
123+
expect(beacon.identifier).toEqual(`${roomId}_${userId}`);
137124
expect(beacon.beaconInfo).toBeTruthy();
138125
});
139126

@@ -171,8 +158,27 @@ describe('Beacon', () => {
171158

172159
expect(beacon.beaconInfoId).toEqual(liveBeaconEvent.getId());
173160

174-
expect(() => beacon.update(notLiveBeaconEvent)).toThrow();
175-
expect(beacon.isLive).toEqual(true);
161+
expect(() => beacon.update(user2BeaconEvent)).toThrow();
162+
// didnt update
163+
expect(beacon.identifier).toEqual(`${roomId}_${userId}`);
164+
});
165+
166+
it('does not update with an older event', () => {
167+
const beacon = new Beacon(liveBeaconEvent);
168+
const emitSpy = jest.spyOn(beacon, 'emit').mockClear();
169+
expect(beacon.beaconInfoId).toEqual(liveBeaconEvent.getId());
170+
171+
const oldUpdateEvent = makeBeaconInfoEvent(
172+
userId,
173+
roomId,
174+
);
175+
// less than the original event
176+
oldUpdateEvent.event.origin_server_ts = liveBeaconEvent.event.origin_server_ts - 1000;
177+
178+
beacon.update(oldUpdateEvent);
179+
// didnt update
180+
expect(emitSpy).not.toHaveBeenCalled();
181+
expect(beacon.beaconInfoId).toEqual(liveBeaconEvent.getId());
176182
});
177183

178184
it('updates event', () => {
@@ -182,7 +188,7 @@ describe('Beacon', () => {
182188
expect(beacon.isLive).toEqual(true);
183189

184190
const updatedBeaconEvent = makeBeaconInfoEvent(
185-
userId, roomId, { timeout: HOUR_MS * 3, isLive: false }, '$live123', '$live123');
191+
userId, roomId, { timeout: HOUR_MS * 3, isLive: false }, '$live123');
186192

187193
beacon.update(updatedBeaconEvent);
188194
expect(beacon.isLive).toEqual(false);
@@ -200,7 +206,6 @@ describe('Beacon', () => {
200206
roomId,
201207
{ timeout: HOUR_MS * 3, isLive: false },
202208
beacon.beaconInfoId,
203-
'$live123',
204209
);
205210

206211
beacon.update(updatedBeaconEvent);

spec/unit/room-state.spec.js

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as utils from "../test-utils/test-utils";
22
import { makeBeaconInfoEvent } from "../test-utils/beacon";
33
import { filterEmitCallsByEventType } from "../test-utils/emitter";
44
import { RoomState, RoomStateEvent } from "../../src/models/room-state";
5-
import { BeaconEvent } from "../../src/models/beacon";
5+
import { BeaconEvent, getBeaconInfoIdentifier } from "../../src/models/beacon";
66

77
describe("RoomState", function() {
88
const roomId = "!foo:bar";
@@ -260,7 +260,7 @@ describe("RoomState", function() {
260260
state.setStateEvents([beaconEvent]);
261261

262262
expect(state.beacons.size).toEqual(1);
263-
const beaconInstance = state.beacons.get(beaconEvent.getType());
263+
const beaconInstance = state.beacons.get(`${roomId}_${userA}`);
264264
expect(beaconInstance).toBeTruthy();
265265
expect(emitSpy).toHaveBeenCalledWith(BeaconEvent.New, beaconEvent, beaconInstance);
266266
});
@@ -275,49 +275,49 @@ describe("RoomState", function() {
275275

276276
// no beacon added
277277
expect(state.beacons.size).toEqual(0);
278-
expect(state.beacons.get(redactedBeaconEvent.getType)).toBeFalsy();
278+
expect(state.beacons.get(getBeaconInfoIdentifier(redactedBeaconEvent))).toBeFalsy();
279279
// no new beacon emit
280280
expect(filterEmitCallsByEventType(BeaconEvent.New, emitSpy).length).toBeFalsy();
281281
});
282282

283283
it('updates existing beacon info events in state', () => {
284284
const beaconId = '$beacon1';
285-
const beaconEvent = makeBeaconInfoEvent(userA, roomId, { isLive: true }, beaconId, beaconId);
286-
const updatedBeaconEvent = makeBeaconInfoEvent(userA, roomId, { isLive: false }, beaconId, beaconId);
285+
const beaconEvent = makeBeaconInfoEvent(userA, roomId, { isLive: true }, beaconId);
286+
const updatedBeaconEvent = makeBeaconInfoEvent(userA, roomId, { isLive: false }, beaconId);
287287

288288
state.setStateEvents([beaconEvent]);
289-
const beaconInstance = state.beacons.get(beaconEvent.getType());
289+
const beaconInstance = state.beacons.get(getBeaconInfoIdentifier(beaconEvent));
290290
expect(beaconInstance.isLive).toEqual(true);
291291

292292
state.setStateEvents([updatedBeaconEvent]);
293293

294294
// same Beacon
295-
expect(state.beacons.get(beaconEvent.getType())).toBe(beaconInstance);
295+
expect(state.beacons.get(getBeaconInfoIdentifier(beaconEvent))).toBe(beaconInstance);
296296
// updated liveness
297-
expect(state.beacons.get(beaconEvent.getType()).isLive).toEqual(false);
297+
expect(state.beacons.get(getBeaconInfoIdentifier(beaconEvent)).isLive).toEqual(false);
298298
});
299299

300300
it('destroys and removes redacted beacon events', () => {
301301
const beaconId = '$beacon1';
302-
const beaconEvent = makeBeaconInfoEvent(userA, roomId, { isLive: true }, beaconId, beaconId);
303-
const redactedBeaconEvent = makeBeaconInfoEvent(userA, roomId, { isLive: true }, beaconId, beaconId);
304-
const redactionEvent = { event: { type: 'm.room.redaction' } };
302+
const beaconEvent = makeBeaconInfoEvent(userA, roomId, { isLive: true }, beaconId);
303+
const redactedBeaconEvent = makeBeaconInfoEvent(userA, roomId, { isLive: true }, beaconId);
304+
const redactionEvent = { event: { type: 'm.room.redaction', redacts: beaconEvent.getId() } };
305305
redactedBeaconEvent.makeRedacted(redactionEvent);
306306

307307
state.setStateEvents([beaconEvent]);
308-
const beaconInstance = state.beacons.get(beaconEvent.getType());
308+
const beaconInstance = state.beacons.get(getBeaconInfoIdentifier(beaconEvent));
309309
const destroySpy = jest.spyOn(beaconInstance, 'destroy');
310310
expect(beaconInstance.isLive).toEqual(true);
311311

312312
state.setStateEvents([redactedBeaconEvent]);
313313

314314
expect(destroySpy).toHaveBeenCalled();
315-
expect(state.beacons.get(beaconEvent.getType())).toBe(undefined);
315+
expect(state.beacons.get(getBeaconInfoIdentifier(beaconEvent))).toBe(undefined);
316316
});
317317

318318
it('updates live beacon ids once after setting state events', () => {
319-
const liveBeaconEvent = makeBeaconInfoEvent(userA, roomId, { isLive: true }, '$beacon1', '$beacon1');
320-
const deadBeaconEvent = makeBeaconInfoEvent(userA, roomId, { isLive: false }, '$beacon2', '$beacon2');
319+
const liveBeaconEvent = makeBeaconInfoEvent(userA, roomId, { isLive: true }, '$beacon1');
320+
const deadBeaconEvent = makeBeaconInfoEvent(userB, roomId, { isLive: false }, '$beacon2');
321321

322322
const emitSpy = jest.spyOn(state, 'emit');
323323

src/@types/beacon.ts

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
import { EitherAnd, RELATES_TO_RELATIONSHIP, REFERENCE_RELATION } from "matrix-events-sdk";
17+
import { RELATES_TO_RELATIONSHIP, REFERENCE_RELATION } from "matrix-events-sdk";
1818

1919
import { UnstableValue } from "../NamespacedValue";
2020
import { MAssetEvent, MLocationEvent, MTimestampEvent } from "./location";
2121

2222
/**
23-
* Beacon info and beacon event types as described in MSC3489
24-
* https://github.com/matrix-org/matrix-spec-proposals/pull/3489
23+
* Beacon info and beacon event types as described in MSC3672
24+
* https://github.com/matrix-org/matrix-spec-proposals/pull/3672
2525
*/
2626

2727
/**
@@ -60,16 +60,11 @@ import { MAssetEvent, MLocationEvent, MTimestampEvent } from "./location";
6060
* }
6161
*/
6262

63-
/**
64-
* Variable event type for m.beacon_info
65-
*/
66-
export const M_BEACON_INFO_VARIABLE = new UnstableValue("m.beacon_info.*", "org.matrix.msc3489.beacon_info.*");
67-
6863
/**
6964
* Non-variable type for m.beacon_info event content
7065
*/
71-
export const M_BEACON_INFO = new UnstableValue("m.beacon_info", "org.matrix.msc3489.beacon_info");
72-
export const M_BEACON = new UnstableValue("m.beacon", "org.matrix.msc3489.beacon");
66+
export const M_BEACON_INFO = new UnstableValue("m.beacon_info", "org.matrix.msc3672.beacon_info");
67+
export const M_BEACON = new UnstableValue("m.beacon", "org.matrix.msc3672.beacon");
7368

7469
export type MBeaconInfoContent = {
7570
description?: string;
@@ -80,16 +75,11 @@ export type MBeaconInfoContent = {
8075
live?: boolean;
8176
};
8277

83-
export type MBeaconInfoEvent = EitherAnd<
84-
{ [M_BEACON_INFO.name]: MBeaconInfoContent },
85-
{ [M_BEACON_INFO.altName]: MBeaconInfoContent }
86-
>;
87-
8878
/**
8979
* m.beacon_info Event example from the spec
90-
* https://github.com/matrix-org/matrix-spec-proposals/pull/3489
80+
* https://github.com/matrix-org/matrix-spec-proposals/pull/3672
9181
* {
92-
"type": "m.beacon_info.@matthew:matrix.org.1",
82+
"type": "m.beacon_info",
9383
"state_key": "@matthew:matrix.org",
9484
"content": {
9585
"m.beacon_info": {
@@ -108,15 +98,15 @@ export type MBeaconInfoEvent = EitherAnd<
10898
* m.beacon_info.* event content
10999
*/
110100
export type MBeaconInfoEventContent = &
111-
MBeaconInfoEvent &
101+
MBeaconInfoContent &
112102
// creation timestamp of the beacon on the client
113103
MTimestampEvent &
114104
// the type of asset being tracked as per MSC3488
115105
MAssetEvent;
116106

117107
/**
118108
* m.beacon event example
119-
* https://github.com/matrix-org/matrix-spec-proposals/pull/3489
109+
* https://github.com/matrix-org/matrix-spec-proposals/pull/3672
120110
*
121111
* {
122112
"type": "m.beacon",

0 commit comments

Comments
 (0)